十八反射
实例化对象:类–>对象
通过:对象–>类名
1.作用
通过反射可使程序代码访问装载到JVM的类的内部信息
获得已装载类的属性信息
获得已装载类的方法
获得已装载类的构造方法信息
2.反射常用类
都位于java.lang.reflect包
Class
代表一个类
反射机制的起源和入口
提供了获取类信息的相关方法
用于获取与类相关的各种信息
常用方法
getPackage() 获得类的所属包
getSuperClass() 获得类的父类对应的Class对象
getName() 获得类的完整名字
getDeclaredConstructors() 获得类所有构造方法
getConstrutors() 获得类public类型的构造方法
getConstrutor(Class[] args) 获得类特定构造方法
getDeclaredFields() 获得类所有属性
getFields() 获得类public类型属性
getField(String name) 获得类指定属性
getDeclaredMethods() 获得类的所有方法
getMethods() 获得类public类型的方法
getMethod(String name,Class[] args) 获得类指定方法
Constructor
代表类的构造方法
Field
代表类的成员属性
Method
代表类的成员方法
Array
代表动态数组的创建以及访问数组元素的静态方法
public class S1Reflect {
public int id=1;
String name="李四";
private int age=14;
public S1Reflect(){
}
public S1Reflect(String name, int age) {
this.name = name;
this.age = age;
}
public void function(){
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
//1.实例化对象
S1Reflect reflect=new S1Reflect();
//通过对象得到对应的反射类
Class<?> c=reflect.getClass();
//通过反射类得到该类对象
S1Reflect reflect2=(S1Reflect) c.newInstance();
System.out.println(reflect2.name);
System.out.println("所属包:"+c.getPackage());
System.out.println("得到父类:"+c.getSuperclass());
System.out.println("类名:"+c.getName());
Constructor<?>[] constructors=c.getDeclaredConstructors();
System.out.print("通过反射类得到所有构造方法:");
for(Constructor constructor:constructors){
System.out.print(constructor.getName()+"\t");
}
System.out.println();
System.out.print("通过反射类得到所有属性:");
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
System.out.print(field.getName()+"\t");
}
System.out.println();
System.out.print("通过反射类得到public类型属性:");
Field[] fieldsP=c.getFields();
for(Field field:fieldsP){
System.out.print(field.getName()+"\t");
}
System.out.println();
System.out.print("通过反射类得到所有方法:");
Method methods[]=c.getDeclaredMethods();
for(Method method: methods){
System.out.print(method.getName()+"\t");
}
System.out.println();
}
}
李四
所属包:package S1022Reflect
得到父类:class java.lang.Object
类名:S1022Reflect.S1Reflect
通过反射类得到所有构造方法:S1022Reflect.S1Reflect S1022Reflect.S1Reflect
通过反射类得到所有属性:id name age
通过反射类得到public类型属性:id
通过反射类得到所有方法:main function
3.生成Class(反射类)的方法
1.对象名.getClass()
3.类名.class
2.Class.forName()
4.包装类.TYPE
public class S2GetReflectClass {
public static void main(String[] args) throws ClassNotFoundException {
//1.通过对象名.getClass()得到反射类
S2GetReflectClass s2GetReflectClass=new S2GetReflectClass();
Class<?> getClassClass=s2GetReflectClass.getClass();
System.out.println("过对象名.getClass()得到反射类:"+getClassClass.getName());
//2.通过对象名class.forName()得到反射类
Class<?> forNameClass=Class.forName("S1022Reflect.S2GetReflectClass");
System.out.println("过对象名.getClass()得到反射类:"+getClassClass.getName());
//3.通过类名.class得到反射类
Class classClass=S2GetReflectClass.class;
System.out.println("通过类名.class得到反射类:"+classClass.getName());
//4.通过包装类.TYPE得到反射类
Class typeClass=Integer.TYPE;
System.out.println("通过包装类.type得到反射类:"+typeClass.getName());
}
}
过对象名.getClass()得到反射类:S1022Reflect.S2GetReflectClass
过对象名.getClass()得到反射类:S1022Reflect.S2GetReflectClass
通过类名.class得到反射类:S1022Reflect.S2GetReflectClass
通过包装类.type得到反射类:int
4.动态创建对象
1.通过Class的newInstance()方法
执行无参构造方法创建该类的实例
2.通过constructor的newInstance()方法
使用Class对象获取指定的Constructor对象
再调用Constructor对象newInstance()方法创建该Class对象 对应类的对象
public class S3DynamicCreate {
public int id;
public String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public S3DynamicCreate(int id, String name) {
this.id = id;
this.name = name;
}
public S3DynamicCreate() {
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> c=Class.forName("S1022Reflect.S3DynamicCreate");
Constructor cons=c.getConstructor(new Class[]{int.class,String.class});
S3DynamicCreate dynamicCreate=(S3DynamicCreate) cons.newInstance(1,"lisi");
System.out.println(dynamicCreate.id+"\t"+dynamicCreate.name);
}
}
1 lisi
5.调用反射类方法
Method getMethod(String name,Class<?>…parameterTypes) 返回一个Method对象
Object invoke(Object obj,Object…args) 对带有指定参数的指定对象调用此Method对象表示底层的方法
public class S4InvokeFunction {
public int fun(int id,String name){
System.out.println("调用fun方法");
return 10;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
Class<?> c=S4InvokeFunction.class;
Object obj=c.newInstance();
Method m=c.getMethod("fun", new Class[]{int.class,String.class});
Object o=m.invoke(obj,new Object[]{1,"aa"});
System.out.println("o:"+o);
}
}
6.反射的特点
优点
反射提高了Java程序的灵活性和扩展性,提高自适应能力,允许程序创建和控制任何类的对象,无需提前编码目标类
缺点
反射是一种解释操作,用于字段和方法接入是远慢于代码,主要应用在灵活性和扩展性要求很高的系统框架
使用反射会模糊程序内部逻辑,反射绕开和源代码的技术,比相应的直接代码更复杂