反射
反射就是根据字节码文件,反射类的信息,字段,方法,构造方法等类的内容,
根据字节码文件创建对象,调用方法的技术
文章目录
反射的基础,是class的对象
- 每一个类都有class属性
- 每个对象都有getClass() 方法
- Class.forName(完整类名)
Class.forName 返回Class对象时,回把参数指定的类加载到内存中
Class<?> class7 = Person.class; //没有执行Person类静态代码块, 说明Person类没有加载内存
Class<?> class8 = Class.forName("com.bjpowernode.chapter08.demo01.Person"); //执行了静态代码块, 说明类加载了内存
反射类的信息
java.lang.reflect包中有反射相关的类
- class1.getModifiers() 返回类的修饰符
- class1.getName() 返回完整类名
- class1.getSimpleName() 简易类名
- class1.getSuperClass() 父类
- class1.getInterfaces() 接口
创建Class对象
Class<?> class1 = String.class;
反射类的信息
修饰类 Modifiers:修饰器
class1.getModifiers();
Modifier.toString(mod);//整数转换为字符串
类名
Simple简单
class1.getName() 返回完整类名
class1.getSimpleName() //返回简易类名
父名
class1.getSuperClass();
Class<?> superclass = class1.getSuperclass();
//判断父类是否为Object
if ( Object.class != superclass ) {
sb.append(" extends ");
sb.append( superclass.getSimpleName() );
}
接口
getInterfaces()
返回接口数组, 如果类没有实现接口,返回的数组长度为0
class1.getInterfaces();
Class<?>[] interfaces = class1.getInterfaces();
if( interfaces.length > 0 ){ //实现了接口
sb.append(" implements ");
//遍历接口数组
for( int i = 0 ; i<interfaces.length ; i++){
sb.append( interfaces[i].getSimpleName() );
//接口之间使用逗号分隔
if ( i < interfaces.length - 1) {
sb.append(",");
}
}
}
通过反射技术访问字段
-
class1.getField(字段名) 返回指定字段名的公共字段
-
class1.getDeclaredField(字段名) 返回指定名称的字段(即使它是私有的)
-
class1.newInstance() 创建一个实例(创建一个对象)
-
field.set(对象名, 字段的值); 设置字段的值
-
field.get(对象名); 返回字段的值
-
field.setAccessible(true); 设置字段的可访问性
创建Class对象,
Class<?> class1 = Person.class;
反射name字段
Field nameF = class1.getField(“name”);
通过反射技术创建对象(实例),默认调用类的无参构造
Object p1 = class1.newInstance(); //相当于new Person()
设置字段的值
nameF.set(p1, “lisi”); //p1.setName(“lisi”)
返回字段的值
System.out.println( p1 );
System.out.println( nameF.get(p1) ); //p1.getName()
访问私有字段 age
Object p1 = class1.newInstance(); //相当于new Person()
Field ageF = class1.getField("age"); //只能返回公共字段
Field ageF = class1.getDeclaredField("age"); //返回字段
ageF.setAccessible(true); //设置字段的可访问性
ageF.set(p1, 18);
System.out.println( ageF.get(p1));
System.out.println( p1 );
通过反射技术调用方法
- class1.getMethod(方法名,参数类型列表) 反射指定方法签名的公共方法
- method.invoke(实例名, 方法的实参列表) 调用方法
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1) 创建Class对象
Class<?> class1 = Person.class;
//2) 反射show()方法
Method showM = class1.getMethod("show", null);
//3)通过反射技术创建实例
Object obj = class1.newInstance(); //new Person()
//4)调用方法
showM.invoke(obj, null); //obj.show()
//5)反射set(String, int)方法
Method setM = class1.getMethod("set", String.class , int.class );
setM.invoke(obj, "lisi", 66);
showM.invoke(obj);
System.out.println( obj );
}
代码
Person类
public class Person {
static{
System.out.println("静态代码块, 在类加载内存后执行");
}
public String name;
private int age;
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public void show() {
System.out.println("name:" + name + ",age:" + age);
}
public void set(String name, int age) {
this.age = age;
this.name = name;
}
}
创建Class对象的方式
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
//1) 每个类都有一个Class属性
Class class1 = Test01.class;
//2)每个 对象有getClass()
Class class2 = new Test01().getClass();
//3) Class.forName()
Class class3 = Class.forName("com.bjpowernode.chapter08.demo01.Test01");
System.out.println( class1 );
//
System.out.println( class1 == class2 );
System.out.println( class2 == class3 );
//4)
Class<?> class4 = int.class;
Class<?> class5 = Integer.class;
System.out.println( class4 == class5 ); //false
Class<?> class6 = Integer.TYPE;
System.out.println( class4 == class6 ); //true
//5) Class.forName()r返回Class对象时, 会把参数指定的类加载到内存中
// Class<?> class7 = Person.class; //没有执行Person类静态代码块, 说明Person类没有加载内存
Class<?> class8 = Class.forName("com.bjpowernode.chapter08.demo01.Person"); //执行了静态代码块, 说明类加载了内存
}
}
反射类的信息
public class Test02 {
public static void main(String[] args) {
//1)创建Class对象
Class<?> class1 = String.class;
// Class<?> class1 = Integer.class;
StringBuilder sb = new StringBuilder();
//2)反射类的信息
//2.1 修饰符
int mod = class1.getModifiers(); //方法返回类的修饰符,是一个整数
String modifier = Modifier.toString(mod);//整数转换为字符串
sb.append( modifier );
//2.2 类名
sb.append(" class ");
// sb.append( class1.getName() ) ; //getName()r返回完整类名
sb.append( class1.getSimpleName() ) ; //返回简易类名
//2.3 父类
Class<?> superclass = class1.getSuperclass();
//判断父类是否为Object
if ( Object.class != superclass ) {
sb.append(" extends ");
sb.append( superclass.getSimpleName() );
}
//2.4 接口,getInterfaces()返回接口数组, 如果类没有实现接口,返回的数组长度为0
Class<?>[] interfaces = class1.getInterfaces();
if( interfaces.length > 0 ){ //实现了接口
sb.append(" implements ");
//遍历接口数组
for( int i = 0 ; i<interfaces.length ; i++){
sb.append( interfaces[i].getSimpleName() );
//接口之间使用逗号分隔
if ( i < interfaces.length - 1) {
sb.append(",");
}
}
}
System.out.println( sb );
}
}
通过反射技术访问字段
public class Test03 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
//1) 创建Class对象,
Class<?> class1 = Person.class;
//2) 反射name字段
Field nameF = class1.getField("name");
//3) 通过反射技术创建对象(实例), 默认调用类的无参构造
Object p1 = class1.newInstance(); //相当于new Person()
//4)设置字段的值
nameF.set(p1, "lisi"); //p1.setName("lisi")
//5)返回字段的值
System.out.println( p1 );
System.out.println( nameF.get(p1) ); //p1.getName()
//6)访问私有字段: age
// Field ageF = class1.getField("age"); //只能返回公共字段
Field ageF = class1.getDeclaredField("age"); //返回字段
ageF.setAccessible(true); //设置字段的可访问性
ageF.set(p1, 18);
System.out.println( ageF.get(p1));
System.out.println( p1 );
}
}
通过反射技术调用方法
public class Test05 {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1) 创建Class对象
Class<?> class1 = Person.class;
//2) 反射show()方法
Method showM = class1.getMethod("show", null);
//3)通过反射技术创建实例
Object obj = class1.newInstance(); //new Person()
//4)调用方法
showM.invoke(obj, null); //obj.show()
//5)反射set(String, int)方法
Method setM = class1.getMethod("set", String.class , int.class );
setM.invoke(obj, "lisi", 66);
showM.invoke(obj);
System.out.println( obj );
}
}