Person p = new Student();
import java.lang.reflect.Method; class Person{ public void speak(){ System.out.println("I am a person"); } } class Student extends Person{ public void speak(){ //覆盖父类方法 System.out.println("I am a student"); } //子类新添加方法 public void study(){ System.out.println("Student can study"); } } public class PSTest { public static void main(String[] args) throws Exception{ Person p = new Student(); //直接调用报错,因为Person中没有study()方法 //p.study(); //第1种解决方法:判断并强制转换类型 if(p instanceof Student){ Student s = (Student)p; s.study(); } //第2种解决方法:运行得到该对象及类信息 Class<?> clazz = p.getClass(); //得到类名 System.out.println(clazz.getName()); //甚至直接调用方法 Method m = clazz.getMethod("study"); m.invoke(p); } }
Package
对象包含有关 Java 包的实现和规范的版本信息。(1)Class类的静态方法forName(String clazzName),字符串参数的值是某个类的全限定类名,必须添加完整包名,注:此方法还有另一种重载形式。
(2)调用某个类的class属性来获取该类对应的Class对象,如Person.class将会返回Person类对应的Class对象。如果只有类的字符串如“java.lang.String”获取该字符串对应的Class对象,只能使用第1种方式,此方法可能抛出ClassNotFoundException异常。一旦获得某个类对应的Class对象,就可以调用Class对象的方法来获得该对象和该类的真实信息。
Class类提供了大量的实例方法来获取Class对象所对应类的详细信息,大致包含如下方法,每个方法又包含多种重载版本:
a. Constructor<?>[] getConstructors():返回此Class对象对应类的所有public构造器。
b.Constructor<T> getConstructor(Class<?>... parameterTypes):返回此Class对象对应类的指定public构造器。
c. Constructor<?>[] getDeclaredConstructors():返回此Class对象对应类的所有构造器,与构造器的访问权限无关。
d.Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):返回此对象对应类的指定构造器,与构造器的访问权限无关。
import java.lang.reflect.Constructor; class Person{ public Person(){ System.out.println("TestTarget"); } public Person(String name){ System.out.println(name); } protected Person(String stuName,String className){ System.out.println(stuName + " - " + className); } private Person(String name, int age){ System.out.println(name + " - " + age); } } public class GetConstructorsTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException{ //1.获得Class对象(共3种方式) //1)Class.forName(String clazzName); //Class<?> clazz = Class.forName("tad.blog.reflect.Person"); //2)类的class属性 Class<Person> clazz = Person.class; //3)对象getClass()方法 //Class<?> clazz = new Person().getClass(); //System.out.println(clazz.getName()); //2.1.获取所有public构造器 Constructor<?>[] publicCons = clazz.getConstructors(); System.out.println("所有public构造器"); for(Constructor<?> c : publicCons){ System.out.println(c.getName()); } //2.2.获取特定public构造器 Constructor<Person> certainCons = clazz.getConstructor(String.class); System.out.println("特定public构造器"); System.out.println("名称:" + certainCons.getName() + ";修饰符: " + certainCons.getModifiers()); //2.3.获取所有构造器 Constructor<?>[] allCons = clazz.getDeclaredConstructors(); System.out.println("所有构造器"); for(Constructor<?> c : allCons){ System.out.println(c.getName()); } //2.4.获取特定构造器,访问修饰符无关 Constructor<Person> certainConsPro = clazz.getDeclaredConstructor(String.class,int.class); System.out.println("特定构造器"); System.out.println("名称:" + certainConsPro.getName() + " ;修饰符: " + certainConsPro.getModifiers()); } }
a. Method[] getMethods():返回此Class对象所表示的类的所有public方法。
b. Method getMethod(String name,Class<?>... parameterTypes):返回此Class对象对应类的指定public方法。
c.Method[] getDeclaredMethods():返回此Class对象对应类的全部方法,与方法的访问权限无关。
d. Method getDeclaredMethod(String name,Class<?>... parameterTypes):返回此对象对应类的指定方法,与方法的访问权限无关。
import java.lang.reflect.Method; class Fruit{ public void show(){ } public void show(String info){ } void getWater(){ } protected void grow(){ } private void deep(){ } private void deep(int length){ } } public class GetMethodsTest { public static void main(String[] args) throws NoSuchMethodException { //1.获得Class对象 Class<Fruit> clazz = Fruit.class; //2.1.获得所有public Method System.out.println("所有public方法"); Method[] publicMethods = clazz.getMethods(); for(Method m : publicMethods){ System.out.println(m.getName()); } //2.2.获得特定public Method System.out.println("特定public方法"); Method certainMethod = clazz.getMethod("show",String.class); System.out.println(certainMethod.getName()); //2.3.获得所有Method,修饰符无关 System.out.println("所有方法"); Method[] allMethods = clazz.getDeclaredMethods(); for(Method m : allMethods){ System.out.println(m.getName()); } //2.4.获得特定Method,修饰符无关 System.out.println("特定方法"); Method certainMethodDeep = clazz.getDeclaredMethod("deep", int.class); System.out.println(certainMethodDeep.getName()); } }
import java.lang.reflect.Field; class Animal{ public String name; public int age; private String secrets; } public class GetFieldsTest { public static void main(String[] args) throws NoSuchFieldException { //1.获得Class对象 Class<Animal> clazz = Animal.class; //2.1.获得所有public字段 Field[] fields = clazz.getFields(); System.out.println("所有public字段"); for(Field f : fields){ System.out.println(f.getName()); } //2.2.获得特定public字段 Field f = clazz.getField("name"); System.out.println("特定public字段"); System.out.println(f.getName()); //2.3.获得所有字段,访问修饰符无关 Field[] allFields = clazz.getDeclaredFields(); System.out.println("获得所有字段"); for(Field af : allFields){ System.out.println(af.getName()); } //2.4.获得特定字段,访问修饰符无关 Field certainField = clazz.getDeclaredField("secrets"); System.out.println("获得特定字段"); System.out.println(certainField.getName()); } }
@Deprecated @Addressing @SuppressWarnings(value="unchecked") class Building{ @Override public String toString(){ return "Building"; } } public class GetAnnotationsTest { public static void main(String[] args) { //1.获得Class对象 Class<Building> clazz = Building.class; //2.1.获得所有Annotation System.out.println("获得所有Annotation"); Annotation[] as = clazz.getAnnotations(); for(Annotation a : as){ System.out.println(a); } //2.2.获得特定Annotation System.out.println("获得特定Annotation"); Annotation a = clazz.getAnnotation(Addressing.class); System.out.println(a); //2.3.获得直接修饰的所有Annotation System.out.println("获得所有Annotation"); Annotation[] ass = clazz.getDeclaredAnnotations(); for(Annotation ann : ass){ System.out.println(ann); } } }
a. Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口。
b. Class<? super T> getSuperClass():返回该Class对象对应类的超类的Class对象。
interface Interfa{ } interface Interfa2{ } final class SuperClass implements Interfa,Interfa2{ public static class InnerClass{ public static void declaringClass() { Class<InnerClass> clazz = InnerClass.class; System.out.println("外部类"); System.out.println(clazz.getDeclaringClass()); } } } public class TestAll{ public static void main(String[] args) { Class<SuperClass> clazz = SuperClass.class; //获得所有内部类 System.out.println("所有内部类"); Class<?>[] inners = clazz.getDeclaredClasses(); for(Class<?> inner : inners){ System.out.println(inner); } //获得外部类 SuperClass.InnerClass.declaringClass(); //获得继承父类 System.out.println("继承父类"); System.out.println(clazz.getSuperclass()); //获得实现接口 System.out.println("实现接口"); Class<?>[] inters = clazz.getInterfaces(); for(Class<?> i : inters){ System.out.println(i); } //获得修饰符 System.out.println("获得修饰符"); int modifier = clazz.getModifiers(); System.out.println(modifier); //获得包 System.out.println("获得包"); Package p = clazz.getPackage(); System.out.println(p.getName()); //获得全类名及简单类名 System.out.println("全类名及简单类名"); System.out.println(clazz.getName()); System.out.println(clazz.getSimpleName()); //自我判断API System.out.println("注解? " + clazz.isAnnotation()); System.out.println("数组? " + clazz.isArray()); SuperClass sc = new SuperClass(); System.out.println("实例? " + clazz.isInstance(sc)); } }
Class对象可以获得该类里的方法(由Method对象表示)、构造器(由Constructor对象表示)、字段(由Field对象表示),这3个类都位于java.lang.reflect包下,并实现java.lang.reflect.Member接口。程序可以通过Method对象执行对应方法,通过Constructor对象调用对应构造器创建实例,能通过Field对象直接访问并修改对象的属性值。
通过反射创建对象有以下两种方式:
(1)使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法实际上利用默认构造器来创建该类的实例。
(2)先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择指定的构造器来创建实例。
通过第一种方式来创建对象是比较常见的情形,在很多JavaEE框架中都需要根据配置文件信息来创建Java对象,从配置文件读取的只是某个类的字符串类名,程序需要根据字符串来创建对应的实例,就必须使用反射。
(3)调用Constructor的newInstance()方法创建Java对象。
import java.lang.reflect.Constructor; class Computer{ public Computer(String name){ show(name); } public void show(){ System.out.println("Computer"); } public void show(String name){ System.out.println("My name is " + name); } } public class ObjFactory { public static void main(String[] args) throws Exception { //Class<Computer> clazz = Computer.class; //1.第1种方式创建对象 //Computer com = clazz.newInstance(); //System.out.println(com); //com.show(); //2.第2种方式创建对象 //2.1.获取Class对象 Class<?> comClazz = Class.forName("tad.blog.reflect.Computer"); //2.2.获得指定构造器 Constructor<?> c = comClazz.getConstructor(String.class); //2.3.创建Java对象 c.newInstance("Tad"); } }
import java.lang.reflect.Field; class Dog { private String name; private int age; public String toString(){ return "Dog[name:"+name+",age:"+age+"]"; } } public class FieldTest { public static void main(String[] args) throws Exception { //创建Person对象 Dog p = new Dog(); //Person对应Class对象 Class<Dog> clazz = Dog.class; //获取Person名为name的Field Field nameField = clazz.getDeclaredField("name"); //取消访问权限 nameField.setAccessible(true); //调用set方法为p对象的name字段值设置值 nameField.set(p,"Tad");//引用类型,没有Xxx,可能是因为引用类型的地址是一样的吧! Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.setInt(p,23);//8个基本数据类型,setXxx() System.out.println(p); } }
每个Method对象对应一个方法,获得Method对象后,程序就可以通过该Method来调用它对应的方法。在Method里包含一个invoke()方法,方法签名如下:
Object invoke(Object obj, Object...args):该方法中的obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参。
import java.lang.reflect.Method; public class MethodTest { public static void main(String[] args) throws Exception { //1.获得Class对象 Class<MethodTest> clazz = MethodTest.class; //2.获得Method对象 Method m = clazz.getMethod("show", String.class); //3.调用invoke()方法 m.invoke(new MethodTest(), "Tad is a great person in the world."); } public void show(String info){ System.out.println(info); } }
在java.lang.reflect包下还提供了一个Array类,Array对象可以代表所有的数组。程序可以使用Array来动态创建数组,操作数组元素等。
(1)static Object newInstance(Class<?> componentType, int length):创建一个具有指定的元素类型、指定维度的新数组。
(2)static xxx getXxx(Object array, int index):返回array数组中第index个元素。其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变为get(Object array, int index)。
(3)static void setXxx(Object array, int index, xxx val):将array数组中第index个元素的值设为val,其中xxx是各种基本数据类型,如果数组元素是引用类型,则该方法变成set(Object array, int index, Object val)。
import java.lang.reflect.Array; public class ArrayTest { public static void main(String[] args) { Object arr = Array.newInstance(String.class, 3); Array.set(arr, 0, "Tad"); Array.set(arr, 1, "great"); Array.set(arr, 2, "person"); System.out.println(Array.get(arr, 0)); System.out.println(Array.get(arr, 1)); System.out.println(Array.get(arr, 2)); System.out.println("长度:" + Array.getLength(arr)); } }
实际上,即使采用第一个方法获取了一个动态代理类之后,当程序需要通过该代理类来创建对象时一样需要传入InvocationHandler对象,也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface Skills{ public void bark(); public void run(); } /** * 委托类,业务执行者 */ class Dog implements Skills{ public void bark() { System.out.println("Dog can bark."); } public void run(){ System.out.println("Dog can run"); } } /** * 调用处理类,完成代理与委托绑定 */ class InvocationHandlerImpl implements InvocationHandler { private Object target; public InvocationHandlerImpl(Object target){ this.target = target; } /** * 方法调用,调用代理到调用委托的转换 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } } public class DynamicProxy { public static void main(String[] args) { InvocationHandler h = new InvocationHandlerImpl(new Dog()); Skills o = (Skills)Proxy.newProxyInstance(Dog.class.getClassLoader(), Dog.class.getInterfaces(), h); o.bark(); o.run(); } }
待补充...
(2)getActualTypeArguments():返回泛型参数的类型。
import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; public class ReflectGenericTest { public int num; public Map<String,Integer> kv; public static void main(String[] args) throws NoSuchFieldException { Class<ReflectGenericTest> c = ReflectGenericTest.class; Field fNum = c.getField("num"); System.out.println(fNum.getType()); //只能输出Map Field f = c.getField("kv"); System.out.println(f.getType()); //获得实际类型参数 Type type = f.getGenericType(); ParameterizedType p = (ParameterizedType) type; System.out.println("原始类型:" + p.getRawType()); Type[] types = p.getActualTypeArguments(); for(Type t : types){ System.out.println(t); } } }
黑马程序员_高新技术_1_Java反射,布布扣,bubuko.com
原文:http://blog.csdn.net/jacklearntech/article/details/29232065