一、反射
1.反射指的是对象的反向处理操作,是根据对象来取得对象的来源信息。
2.类的对象的三种产生模式
(1)任何类的对象可以通过Object类中的getClass()方法取得Class类对象。
(2)"类.class":直接根据某个具体的类来取得Class类的对象。
3.反射调用普通方法
注意:类中的所有属性一定在类对象实例化之后才会进行空间分配,所以此时如果想要调用类的属性,必须保证有实例化对象。
在Class类中提供有两组取得属性的方法:
(1)第一组(包括父类中)-取得类中全部属性:public Field[] getFields() throws SecurityException
(2)第一组(包括父类中)-取得类中指定名称属性:public Field getField(String name) throws NoSuchFieldException, SecurityException
(3)第二组(仅在本类中)-取得类中全部属性:public Field[] getDeclaredFields() throws SecurityException
(4)第二组(仅在本类中)-取得类中指定名称属性:public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
1.反射指的是对象的反向处理操作,是根据对象来取得对象的来源信息。
2.类的对象的三种产生模式
(1)任何类的对象可以通过Object类中的getClass()方法取得Class类对象。
(2)"类.class":直接根据某个具体的类来取得Class类的对象。
(3)使用Class类提供的方法:
public static Class<?> forName(String className) throws ClassNotFoundException
如:
public class Test { public static void main(String[] args) throws ClassNotFoundException { Date date = new Date(); System.out.println(date.getClass()); //(1) System.out.println(Date.class); //(2) System.out.println(Class.forName("java.util.Date")); //(3) } }3.利用反射进行实例化对象
在Class类中定义有如下方法:
public T newInstance() throws InstantiationException, IllegalAccessException
如:
public class Test{ public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Date date = new Date(); Class<?> class1 = date.getClass(); Class<?> class2 = Date.class; Class<?> class3 = Class.forName("java.util.Date"); Object object1 = class1.newInstance(); Object object2 = class2.newInstance(); Object object3 = class3.newInstance(); System.out.println(object1); System.out.println(object2); System.out.println(object3); } }二、反射与类操作
反射操作形式
1.取得父类信息
(1)取得类的包名称:
public Package getPackage()
(2)取得父类的Class对象:
public native Class<? super T> getSuperclass()
(3)取得实现的父接口:
public Class<?>[] getInterfaces()
如:
interface IFruit{} interface IMessage{} class Father{} class CLS extends Father implements IFruit,IMessage {} public class Test{ public static void main(String[] args) { Class<?> class1 = CLS.class; System.out.println(class1.getPackage()); //取得包名称 System.out.println(class1.getSuperclass()); //取得父类名称 Class<?>[] classes = class1.getInterfaces(); //取得实现的父接口 for (Class<?> class2 : classes) { System.out.println(class2); } } }2.反射调用构造
(1)取得指定参数类型的构造:
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
(2)取得类中的所有构造:
public Constructor<?>[] getConstructors() throws SecurityException
如:取得类中的所有构造信息
class Person{ public Person() {} public Person(String name) {} public Person(String name,int age) {} } public class Test{ public static void main(String[] args) { Class<?> class1 = Person.class; Constructor<?>[] constructor = class1.getConstructors(); for (Constructor<?> constructor2 : constructor) { System.out.println(constructor2); } } }
如:通过Constructor类实例化对象
class Person{ private String name; private int age; public Person(String name,int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } public class Test{ public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class<?> class1 = Person.class; Constructor<?> constructor = class1.getConstructor(String.class,int.class); System.out.println(constructor.newInstance("小明",10)); } }注意:在定义简单Java类的时候一定要保留一个无参构造,Class类通过反射实例化对象的时候,只能够调用类中的无参构造。如果现在类中没有无参构造,则无法使用Class类调用,只能通过明确的构造调用实例化处理。
3.反射调用普通方法
取得全部普通方法:
public Method[] getMethods() throws SecurityException
取得指定普通方法:
public Method getMethod(String name, Class<?>... parameterTypes)
调用:
public Object invoke(Object obj, Object... args)throws IllegalAccessException, IllegalArgumentException,InvocationTargetException
如:
class Person{ private String name; private int age; public Person() {} public Person(String name,int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class Test{ public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class<?> class1 = Person.class; Method[] methods = class1.getMethods(); //获取一个类的全部普通方法 for (Method method : methods) { System.out.println(method); } System.out.println("******************************************"); //分割线 //任何时候调用类中的普通方法都必须有实例化对象 Object object = class1.newInstance(); //取得setName这个方法的实例化对象,设置方法名称与参数类型 Method Name = class1.getMethod("setName", String.class); //通过Method类对象调用指定的方法,调用方法需要有实例化对象,同时传入参数 Name.invoke(object, "小明"); //相当于Person类对象.setName("小明") //取得setAge这个方法的实例化对象,设置方法名称与参数类型 Method Age = class1.getMethod("setAge", int.class); //通过Method类对象调用指定的方法,调用方法需要有实例化对象,同时传入参数 Age.invoke(object, 10); //相当于Person类对象.setAge(10) System.out.println(object); } }4.反射调用类中的属性
注意:类中的所有属性一定在类对象实例化之后才会进行空间分配,所以此时如果想要调用类的属性,必须保证有实例化对象。
在Class类中提供有两组取得属性的方法:
(1)第一组(包括父类中)-取得类中全部属性:public Field[] getFields() throws SecurityException
(2)第一组(包括父类中)-取得类中指定名称属性:public Field getField(String name) throws NoSuchFieldException, SecurityException
(3)第二组(仅在本类中)-取得类中全部属性:public Field[] getDeclaredFields() throws SecurityException
(4)第二组(仅在本类中)-取得类中指定名称属性:public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
如:取得类中全部属性
class Person{ public String name; private int age; } class Students extends Person{ private String school; public int num; } public class Test{ public static void main(String[] args) { Class<?> class1 = Students.class; {//普通代码块 //第一组-取得类中全部属性 Field[] fields = class1.getFields(); for (Field field : fields) { System.out.println(field); } } System.out.println("**********************************"); { //第二组-取得类中全部属性 Field[] fields = class1.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } } } }注意:第一组只能取得public的;第二组既能取得public的,也能取得private的。
还有几个重要方法:
(1)设置属性内容:
public void set(Object obj, Object value) throws IllegalArgumentException,IllegalAccessException
(2)取得属性内容:
public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException
(3)动态设置封装:
public void setAccessible(boolean flag) throws SecurityException
(4)取得属性的类型:
public Class<?> getType()
如:
class Person{ public String name; //public 修饰 private int age; //private 修饰 } public class Test{ public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InstantiationException { Class<?> class1 = Person.class; Object object = class1.newInstance(); { Field nameField = class1.getDeclaredField("name"); nameField.set(object, "小明"); //相当于 对象.name = "小明" System.out.println(nameField.get(object)); } System.out.println("************************************"); { //因为是private修饰的,所以会报错 // Field ageField = class1.getDeclaredField("age"); // ageField.set(object, 10); // System.out.println(ageField.get(object)); //动态设置封装 Field ageField = class1.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(object, 10); System.out.println(ageField.get(object)); } System.out.println("************************************"); { //取得属性类型 Field nameField = class1.getDeclaredField("name"); Field ageField = class1.getDeclaredField("age"); System.out.println(nameField.getType()); System.out.println(ageField.getType()); } } }反射继承结构