package cn.sxt.t01; import java.util.Arrays; public class Users { public Integer id; public String name; private String email; private String password; @Override public String toString() { return "Users [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + "]"; } public Users(){ System.out.println("我是无参数构造器!!!!"); } public Users(String name){ System.out.println("我是有参数构造器 :"+name); } private Users(String name,Integer age){ System.out.println("我叫 :"+name+", 今年 :"+age); } public void say(){ System.out.println("你好,世界"); } public void hello1() { System.out.println("我是无参数无返回值方法"); } public String hello2(String name) { return "你好 :"+name; } private String hello3(String name,int age) { return "我是 :"+name+",今年 :"+age; } public static void staticMethod(String name) { System.out.println("我是静态方法 :"+name); } public static void method1(int...intArr) { System.out.println(Arrays.toString(intArr)); } public static void method2(String[] strArr) { System.out.println(Arrays.toString(strArr)); } }
package cn.sxt.t01; import static org.junit.Assert.*; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Date; import java.util.Iterator; import org.junit.Test; public class ClassTest01 { private static Date getObject; /*反射:(reflection):在运行时期,动态地去获取类中的信息(类的信息,方法信息,构造器信息,字段等信息进行操作); 一个类中包含的信息有: 构造器,字段,方法 如何使用反射描述这些相关的信息 Class : 描述类 Method : 描述方法 Constructor :描述构造器 Field :描述字段 * */ @Test public void testName() throws Exception { //编译类型 //运行类型(真实类型) Object obj = new java.util.Date(); //需求:根据对象obj调用Date类中的一个方法,toLocaleString,如何来做? //方案一: 强转 Date d = (Date)obj; System.out.println(d.toLocaleString()); } //方案二: 使用反射 public Object getObject() { return new java.util.Date(); } @Test//获取类的Class实例三种方式 public void testName1() throws Exception { /* * 在任何反射的操作之前,都必须先获取某一个类的字节码实例,任何一个类在jvm有且只有一份字节码实例 * * 获取字节码实例有三种方式 * 1. 类名.class; * 2. 对象.getClass(); * 3. Class.forName("类的全限定名"); * 全限定名 = 包名+类名 * */ // 需求:获取User类的字节码实例 // 1. 类名.class; Class<Users> clz1=Users.class; System.out.println(clz1); // 2. 对象.getClass(); Users users=new Users(); Class<?> clz2= users.getClass(); System.out.println(clz2); // 3. Class.forName("类的全限定名"); // 全限定名 = 包名+类名 Class<?> clz3 = Class.forName("cn.sxt.t01.Users"); System.out.println(clz3); } @Test//获取九大内置类的字节码实例 public void testName2() throws Exception { /*对于对象来说,可以直接使用对象.getClass()或者Class.forName(className); 类名.class都可以获取Class实例. 但是我们的基本数据类型,就没有类的权限定名,也没有getClass方法. 问题: 那么如何使用Class类来表示基本数据类型的Class实例? 八大基本数据类型和 void关键字都是有 字节码实例的 byte,short,int,long,char,float,double,boolean ,void关键字 答 : 数据类型/void.class 即可 每个基本数据类型都是包装类型 如 :int ----Integer包装类型 注意: 基本数据类型和包装数据类型底层的字节码实例是不相同 */ //数据也是一种数据类型,也需要单独获取字节码实例 Class clz = 数据类型[].class //获取8大基本数据类型和void的字节码实例(以int,integer为列) // 1.获取int类型的字节码实例 Class<?> intClz=int.class; System.out.println(intClz); // 其他七种基本数据类型 和 第一种相似.... // 获取void的字节码实例 Class <?> voidClz=void.class; System.out.println(voidClz); // 所有的基本数据类型都有包装类型 // int---Integer // int 和Integer 的字节码是绝对不相等的 Class<Integer> integeClz=Integer.class; System.out.println(integeClz); System.out.println(intClz == integeClz);//false // 直接通过数组类型获取字节码实例 Class<int[]> clz1=int[].class; System.out.println(clz1); // 定义一个数据 int[] arr1 = { 1, 2, 3, 5 }; Class<int[]> clz2=(Class<int[]>)arr1.getClass(); System.out.println(clz2); // 定义一个数据 int[] arr2 = { 10, 2, 3, 5 }; // 3.获取arr1数组的字节码实例 Class<int[]> clz3 = (Class<int[]>) arr2.getClass(); System.out.println(clz3); System.out.println(clz1 == clz2);//true System.out.println(clz3 == clz2);//true //所以不同数组的字节码实例是相同的 } @Test public void testName3() throws Exception { /*类的构函数有 有参数构造函数,无参构造函数,公共构造函数,非公共构造函数,根据不同的构造函数 Class提供了几种获取不同构造函数的方法 * * * 获取Users类的构造器 * * 1.获取Users类的字节码实例 * 2.获取Users对应的构造器 */ //1.获取Users类的字节码实例 Class<Users> stu=Users.class; //2.获取所有的公共构造器 Constructor<?>[] constructors = stu.getConstructors(); for(Constructor<?> constructor:constructors){ System.out.println(constructor); } //3.获取所有的构造器(和访问权限无关) Constructor<?>[] de = stu.getDeclaredConstructors(); for(Constructor<?> constructor : de){ System.out.println(constructor); } //4.获取指定的构造器(公共的)getConstructor Constructor<Users> constructor1 = stu.getConstructor(String.class); System.out.println(constructor1); //5. getDeclaredConstructor 获取和访问权限无关构造器 Constructor<Users> constructor2 = stu.getDeclaredConstructor(String.class,Integer.class); System.out.println(constructor2); } @Test public void testName4() throws Exception { /*调用构造器,创建对象 Constructor<T>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器 常用方法: public T newInstance(Object... initargs):如调用带参数的构造器,只能使用该方式. 参数:initargs:表示调用构造器的实际参数 返回:返回创建的实例,T表示Class所表示类的类型 如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象. public Object newInstance():相当于new 类名(); 调用私有的构造器: * * */ //需求: 使用反射创建Student的java对象 //1.获取字节码实例 //Class<?> clz = Class.forName("cn.sxt.t01.Users"); Class<Users> clz = (Class<Users>)Class.forName("cn.sxt.t01.Users"); //2.获取指定构造器 Constructor<Users> cons1 = clz.getConstructor(String.class); //2.1获取私有构造函数 Constructor<Users> cons2 = clz.getDeclaredConstructor(String.class,Integer.class); //3.创建对象 //3.1. 如果当前类的字节码有一个无参公共数构造器,可以直接使用字节码实例直接创建对象 Users n= clz.newInstance(); n.say(); //3.2.使用构造器创建对象; Users n1 = cons1.newInstance("dewjfe"); //3.3使用私有构造函数创建 //3.3.1设置忽略访问修饰的权限 //如果是私有构造方法,反射默认是无法直接执行的,找到父类中AccessibleObject的方法,设置为true,即可忽略访问权限 cons2.setAccessible(true); Users n3 = cons2.newInstance("fewfew",20); } @Test public void testName5() throws Exception { /*操作方法-Method 一个类创建对象以后,一般就要执行对象的方法等等,使用反射操作对象 首先要获取方法,再去执行,使用Class 获取对应的方法: getMethods() 获取所有的公共方法,包括父类的公共方法 getDeclaredMethods() 获取所有本类的方法,包括本类的私有方法 getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定方法名称的方法,和访问权限无关 ame : 指定的方法名称 parameterTypes : 方法参数的类型 Method执行方法:方法获取以后就需要执行。Method对象中提供方法执行的功能 invoke(Object obj, Object... args) 执行方法 Obj :如果是对象方法,传指定的对象,如果是类方法,传 null Args: 方法的参数 如果方法有返回结果,可以接收 获取方法和方法的执行 一个类中的方法有很多,无参,有参,静态,可变参数私有方法,等等,针对不同的方法处理,提供了不同的获取方案 */ /* * 需求:获取Users类的方法 */ //1.获取Users的字节码实例 Class<Users> clz=Users.class; //2.通过类的字节码直接创建对象(必须保证类有一个无参数公共构造函数) Users newInstance = clz.newInstance(); //3.获取方法 //3.1获取所有的公共方法(包含父类的方法) Method[] methods = clz.getMethods(); for (Method method : methods) { System.out.println(method); } //3.2获取当前类的所有的方法(不包含父类,和访问权限无关,成员或者静态方法都获取) Method[] de = clz.getDeclaredMethods(); for (Method method :de) { System.out.println(method); } //3.3获取指定名称的方法 Method hello1 = clz.getMethod("hello1"); System.out.println(hello1); //3.4 获取私有方法 Method hello3 = clz.getDeclaredMethod("hello3", String.class,int.class); System.out.println(hello3); //3.5获取静态方法 Method staticMethod = clz.getDeclaredMethod("staticMethod", String.class); System.out.println(staticMethod); //3.6获取有数组参数的方法 Method method1 = clz.getDeclaredMethod("method1", int[].class); System.out.println(method1); System.out.println("------------------------------------------------------------"); } @Test public void testName6() throws Exception { //1.获取Users的字节码实例 Class<Users> clz=Users.class; //2.通过类的字节码直接创建对象(必须保证类有一个无参数公共构造函数) Users n = clz.newInstance(); //3.获取方法 //3.1获取指定名称的方法 Method hello1 = clz.getMethod("hello1"); System.out.println(hello1); //3.1.1执行无参数对象方法 hello1.invoke(n); //3.3 获取私有方法 Method hello3 = clz.getDeclaredMethod("hello3", String.class,int.class); System.out.println(hello3); //3.3.1设置忽略访问权限 hello3.setAccessible(true); //3.3.2 执行私有方法 Object invoke = hello3.invoke(n, "令狐冲",30 ); System.out.println( invoke); //3.4获取静态方法 Method staticMethod = clz.getDeclaredMethod("staticMethod", String.class); System.out.println(staticMethod); //3.4.1执行静态方法 staticMethod.invoke(null, "金毛狮王"); //3.5获取基本数据类型整数组参数的方法 Method method1 = clz.getDeclaredMethod("method1", int[].class); System.out.println(method1); //3.5.1执行 数组参数的方法 int[] intArr = {1,2,5,10}; method1.invoke(null, new Object[] {intArr}); //3.6获取基本数据类型整数组参数的方法 Method method2 = clz.getDeclaredMethod("method2", String[].class); System.out.println(method2); //3.6.1执行字符串数组参数的方法 String[] stringArr = {"A","B","D"}; //如果方法中有可变参数(数组),如果反射传递的可变参数是引用类型,底层有一个拆箱的功能,会将数组的元素拆成一个个参数传递过来 //解决方案: 将数组外面在包装一层数组,如果拆箱一次,得到还是一个数组` method2.invoke(null, new Object[] {stringArr}); } @Test public void testName7() throws Exception { /*操作字段(成员变量)-Field * 类中的字段有各种数据类型和各种访问权限,针对这些情况,反射操作有对应的方法来获取和处理 * getFields() 获取当前Class所表示类中所有的public的字段,包括继承的字段. * getDeclaredFields() 获取当前Class所表示类中所有的字段,不包括继承的字段. * getField(String name) 获取当前Class所表示类中该fieldName名字的字段,不包括继承和私有的字段. * getDeclaredField(String name):获取当前Class所表示类中该fieldName名字的字段,不包括继承的字段. * */ /* * Field类常用方法: void setXX(Object obj, XX value) :为基本类型字段设置值,XX表示基本数据类型 void set(Object obj, Object value) :表示为引用类型字段设置值 参数: obj: 表示字段底层所属对象,若该字段是static的,该值应该设为null value: 表示将要设置的值 ------------------------------------------------------------------------------------- XX getXX(Object obj) :获取基本类型字段的值,XX表示基本数据类型 Object get(Object obj) :表示获取引用类型字段的值 参数: obj: 表示字段底层所属对象,若该字段是static的,该值应该设为null 返回:返回该字段的值. * * * *set(Object obj, Object value) 设置引用类型的值,非基本数据类型 Obj: 要设置值得对象 Value : 要设置的值/ /*Field操作设置值/获取值 * 给某个类中的字段设置值和获取值: 1,找到被操作字段所在类的字节码 2,获取到该被操作的字段对象 3,设置值/获取值 * */ /* * 需求:操作Users类的字段 */ // 1.获取Users字节码实例 Class<Users> clz=Users.class; // 1.1 通过字节码实例创建对象(必须保证有一个无参数public构造器) Users n = clz.newInstance(); // 2.获取所有public字段 Field[] fields = clz.getFields(); for (Field field : fields) { System.out.println(field); } // 3.获取所有的字段(与访问权限无关) Field[] declaredFields = clz.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field); } // 4.获取指定名称的public字段 Field field = clz.getField("name"); // 4.1为字段设置值 /* * nameField.set(obj, value); obj : 要设置值字段对应的对象 value :具体指 */ field.set(n, "fewwwfeg"); // 5.获取指定名称的和访问权限无关的字段 Field emailField = clz.getDeclaredField("email"); // 5.1 设置忽略访问权限 emailField.setAccessible(true); // 5.2 设置私有字段的值 emailField.set(n, "xln@qq.com"); System.out.println(n); }}
package cn.sxt.t01; public interface User { int tymp(); }
package cn.sxt.t01; import java.util.Arrays; public class Users implements User{ @Override public int tymp() { return 0; } }
package cn.sxt.t01; import static org.junit.Assert.*; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.junit.Test; public class ClassTest01 { @Test public void testName9() throws Exception { //1.获取Users实现类的字节码实例 Class<Users> clz=Users.class; //获取字节码的接口 //获取字节码的接口 Class<?>[] interfaces = clz.getInterfaces(); for (Class<?> class1 : interfaces) { System.out.println(class1); } //获取字节码实例的权限的名 System.out.println(clz.getName()); //获取简单类名 System.out.println(clz.getSimpleName()); //获取包 System.out.println(clz.getPackage()); } }
JavaBean
问题: 什么是javaBean?
答: JavaBean就是一个个Java类,在java中符合JavaBean特点类才叫做JavaBean
JavaBean的三个特点
- JavaBean类的修饰符必须是public,也就是一个JavaBean必须是一个对应一个类文件
- JavaBean必须有无参数公共构造方法(以便于反射直接通过直接通过字节码实例创建对象)
- JavaBean中的成员变量/字段必须有get/set方法提供对应的属性
JavaBean中的属性
Java类有成员变量,成员变量绝对不是属性,JavaBean中的属性是有get/set方法确定的
Get方法确定属性
public String getName() {
return name;
}
属性确定规则 : get方法去掉 get前缀 ,剩余部分 首字母小写
属性名称 : name
Set方法确定属性
public void setName(String name) {
this.name = name;
}
属性确定规则 : set方法去掉 set前缀 ,剩余部分 首字母小写
属性名称 : name
如果一个成员变量get/set方法都有确定的属性就只有一个
问题 :get/set方法确定确定的属性一般不就和成员变量一样啊,为什么要有属性了
答: 一般情况下,Eclipse工具有自动生成get/set方法的功能,确定的JavaBean的属性只是恰好和成员变量相同,但是成员变量不是属性
如下特殊性情况,属性和成员变量名称不同
//Filed
private String firstName;
//Filed
private String lastName;
//属性 : fullName
public String getFullName() {
return this.firstName + this.lastName;
}
package cn.sxt.crm.pojo; public class Student { private Integer id; private String name; private Integer age; private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Student(Integer id, String name, Integer age, String password) { super(); this.id = id; this.name = name; this.age = age; this.password = password; } public Student() { super(); // TODO Auto-generated constructor stub } }