反射机制可以用来:
- 分析类的能力(调用一个类的方法)
- 运行时查看对象(可以查看类的属性和属性值,比如toString()方法)
- 实现通用的数组操作代码(没懂)
- 利用Method对象,像c++中的指针(懵逼,还是不懂 )
System.out.println(to1.getClass().getName());//com.example.TestProject.test2021.reflect.TestObject
System.out.println(to1.getClass().getSimpleName());//TestObject
System.out.println(to1.getClass().isInterface());//false
可以看到xx.getClass.getName()会打印出这个对象的所属类的包名,还是有挺多方法的。
获得Class类对象的三种方式:
TestObject to1 = new TestObject("第一个对象",1);
System.out.println(to1.getClass());
System.out.println(TestObject.class);
try {
System.out.println(Class.forName("com.example.TestProject.test2021.reflect.TestObject"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
三种方式都是打印出class com.example.TestProject.test2021.reflect.TestObject,效果都是一样的,但是第三种会有异常抛出。
一个Class对象是表示的是一个类型,也就是一个Class对象描述的是一个类,描述这个类的所有信息,因为可以根据Class对象来查看到这个类的所有属性(公有的和私有的),构造器,方法。
TestObject to1 = TestObject.class.newInstance();
newInstance()方法会返回一个默认构造器创建的对象,如果没有默认构造器就会报错。
java.lang.reflect包中有三个类,Field,Method,Constructor,分别对象一个类的属性,方法,构造器。
属性
本来我以为getDeclaredFields()方法只会获取到私有属性,结果是获取到到了公有属性和私有属性,方法都是一样的,就是方法名有区别。
System.out.println(m.getName());//方法名称
System.out.println(m.getDeclaringClass());//class com.example.TestProject.test2021.reflect.TestObject 好像是获取这个方法的所属类的所在包名
System.out.println(m.getName() +" : "+m.getReturnType());// 方法的返回值 class java.lang.String void
if(m.getName().equals("noArgsPrivateMethod")){
System.out.println(m.getExceptionTypes()[0].getName()); //java.lang.NullPointerException 打印一下throws的异常类 但是如果是try-catch m.getExceptionTypes()只是一个空数组
}
System.out.println(m.getName()+" : "+m.getParameterCount()); // 方法的参数的个数
System.out.println(m.getName()+"-------"+Modifier.isPublic(m.getModifiers())); // 判断是不是public修饰的
Class[] params = m.getParameterTypes(); //返回参数的Class对象
for(Class c : params){
System.out.println(c.getSimpleName()); //String Integer String
}
构造器
方法和上面的大同小异,判断访问修饰符,获取参数啊 方法名称都一样的。
敲完代码之后,在看书上,有了一些发现。
- getFields和getDeclaredFields方法会返回这个类及其超类的属性
- 如果属性都是基本类型或者数组类型,那么getFields和getDeclaredFields将会返回一个长度为0的数组。
- getMethods会返回这个类所有的公有方法包括超类的公有方法,getDeclaredMethods只会返回这个类所有的方法,不包括超类的方法。
可以通过Field.get(Object obj)来获得obj中这个Field属性的值,因为TestField的name属性是private的,所以需要nameField.setAccessible(true)设置一下,也可以通过Field.set(obj,val)修改一下obj的属性的值。
方法也是可以通过反射调用的,private方法的话需要设置argsPrivateMethod.setAccessible(true);
Class testClass = TestObject.class;
Constructor constructor = testClass.getConstructor(String.class,Integer.class);
TestObject to1 = (TestObject) constructor.newInstance("newInstance的name",12);
System.out.println(to1.toString()); // TestObject{name='newInstance的name', age=12, nation='null'}
可以通过Constructor.newInstance(xxxx,xxx)构建一个对象。



