java的反射
反射小结
Class:是一个类;一个描述类的类
Method:是一个描述方法的类;
Filed:是一个描述字段的类;
Constructor:是一个描述构造器的类;
1.得到Class对象的三种方法
- Class clazz = 类名.class;
- Class clazz = 对项目.getClass();
- Class clazz = Class.forName("全类名");
2.获取Method:
- getMethods():不能获取私有的方法,但是可以获取到所继承的方法;
- getDeclaredMethods():不能获取到继承的方法;私有方法要跳过验证
- getDeclaredMethod(String methondName,Class … parameterTypes):获取单个方法,如果有参数则需要传入参数
3.执行Method:
- 如果调用的方法是私有的话就需要跳过安全验证setAccessible(true);
- method.invoke(obj,Object … args);
4.获取Field:
- getFields():不能获取私有的字段,但是可以获取到所继承的字段;
- getDeclaredFields():不能获取到继承的字段;私有字段要跳过验证
- getDeclaredField(String fieldName):获取单个字段
5.获取Field的值:
- 私有的字段就需要跳过安全检查setAccessible(true);
- field.get(obj);
6.设置Field的值:
- 私有字段跳过安全验证
- filed.set(obj,value);
7.获取构造器:
- getConstructors();获取所有构造器;
- getConstructor(Class<?>...parameterTypes);获取单个构造器(可以获取带参构造器)
8.通过构造器创建实例
- constructor.newInstance();如果有参数则获取有参构造器把参数传入即可
9.反射获取父类的泛型
- getGenericSuperClass():获取到带泛型的父类
- Type是一个空的接口,是用的时候要使用他的子接口ParameterizedType
- 调用getActualTypeArguments()返回父类的泛型数组
10.反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,也可以得到这个类实现了那些接口;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
对于每一个类而言,JRE都为其保留了一个不变的Class类形的对象。一个Class对象包含了特定某个类的有关信息。
-class对想只能有系统创建对象
-一个类在jvm中只会有一个Class的实列
-每一个类的实例都会记得自己是有哪一个Class实力所生成的。
1.1常用的工具类
Class类
java的类加载机制
ClassLoader类加载器
Constructor 、Method、Field(字段)
native(本地的)关键字,这个是修饰方法是一个原生态的方法,方法的实现不是当前的文件,而是使用其他的语言实现在文件中。java原因本身是无法对系统底层进行访问和操作的,但是可以通过JNI接口调用其它的语言来实现对底层的访问。
2.反射的使用
是用到的类:
Person:
Student:
Person(接口):
Emp(泛型):
1.获取类的三种方式
通过这三种方法获取到的Class是同一个,都是相等的.
2.通过Class创建对象
3.获取对象的所有的方法
/1.获取类里面的方法,可以获取到接口的,继承的,但是无法获取私有的方法;
/2.获取到当前这个类的所以的方法,所有声明的方法,都可以获取到,且只获取当前类的方法,也可以获取到接口实现的方法,但是不能获取到继承的方法
注意,执行一个私有的方法的时候需要跳过安全验证
1 package reflect; 2 3 import entity.Person; 4 5 import java.lang.reflect.InvocationTargetException; 6 import java.lang.reflect.Method; 7 8 /** 9 *Description:java_project 10 *CreatedbySMO992079on2019/6/1112:48 11 */ 12 public class ReflectGetMetHods{ 13 14 private static Class clazz; 15 16 static{ 17 try{ 18 clazz=Class.forName("entity.Person"); 19 }catch(ClassNotFoundExceptione){ 20 e.printStackTrace(); 21 } 22 } 23 24 public static void testMethod(){ 25 //1.获取类里面的方法,可以获取到接口的,继承的,但是无法获取私有的方法; 26 Method[] methods = clazz.getMethods(); 27 for(Methodmethod:methods){ 28 System.out.print(" "+method.getName()); 29 } 30 System.out.println(); 31 32 //2.获取到当前这个类的所以的方法,所有声明的方法,都可以获取到,且只获取当前类的方法,也可以获取到接口实现的方法,但是不能获取到继承的方法 33 Method[] declaredMethods = clazz.getDeclaredMethods(); 34 for(Method method:declaredMethods){ 35 System.out.print(""+method.getName()); 36 } 37 System.out.println(); 38 39 //3.获取一个指定的方法,如果有参数的话需要穿一个参数类型例如privatevoidchangeName(Stringname) 40 MethodchangeName=null; 41 try{ 42 //通过getMethod()这个方法是获取不到私有的方法的。回报java.lang.NoSuchMethodException这个错误 43 //changeName=clazz.getMethod("changeName",String.class); 44 changeName=clazz.getDeclaredMethod("changeName",String.class); 45 changeName.setAccessible(true);//私有方法的加必须跳过安全验证 46 System.out.println(changeName); 47 }catch(NoSuchMethodExceptione){ 48 e.printStackTrace(); 49 } 50 //4.执行一个方法 51 try{ 52 Person o = (Person)clazz.newInstance(); 53 changeName.invoke(o,"张三"); 54 System.out.println(o.getName()); 55 }catch(InstantiationExceptione){ 56 e.printStackTrace(); 57 }catch(IllegalAccessExceptione){ 58 e.printStackTrace(); 59 }catch(InvocationTargetExceptione){ 60 e.printStackTrace(); 61 } 62 63 64 } 65 66 public static void main(String[]args){ 67 testMethod(); 68 } 69 }
4.获取对象的所有的字段
1 public static void testgetFiled(){ 2 3 //1.获取本类的所有的字段,但是无法获取到父类的字段 4 5 Field[] declaredFields=clazz.getDeclaredFields(); 6 7 for(Fieldfield:declaredFields){ 8 9 System.out.println(field.getName()); 10 11 } 12 13 14 15 //2.获取指定的字段 16 17 Field name=null; 18 19 try{ 20 21 name=clazz.getDeclaredField("name"); 22 23 System.out.println(name.getName()); 24 25 }catch(NoSuchFieldExceptione){ 26 27 e.printStackTrace(); 28 29 } 30 31 //3.使用字段 32 33 Person person=newPerson("张三",18); 34 35 name.setAccessible(true);//跳过安全验证 36 37 try{ 38 39 Objecto=name.get(person); 40 41 System.out.println(o); 42 43 }catch(IllegalAccessExceptione){ 44 45 e.printStackTrace(); 46 47 } 48 49 //3.1给一个字段复制 50 51 try{ 52 53 name.set(person,"李四"); 54 55 System.out.println(name.get(person)); 56 57 }catch(IllegalAccessExceptione){ 58 59 e.printStackTrace(); 60 61 } 62 63 }
5.获取一个类的构造器
1 Public static void testgetConstructors()throws NoSuchMethodException,IllegalAccessException,InvocationTargetException,InstantiationException{ 2 3 //1.获取本类所有的构造器 4 5 Constructor[] constructors=clazz.getConstructors(); 6 7 for(Constructor constructor :constructors ){ 8 9 System.out.println(constructor); 10 11 } 12 13 //2.获取指定的构造器 14 15 Constructor<Person>constructor=clazz.getConstructor(); 16 17 18 19 //2.1获取指定带参数的构造器 20 21 Constructor<Person>constructor1=clazz.getConstructor(String.class,int.class); 22 23 24 25 //3.通过构造器来创建对象 26 27 Personperson=constructor.newInstance(); 28 29 System.out.println(person); 30 31 32 33 //3.1通过有参数的构造器来创建对象 34 35 Personperson1=constructor1.newInstance("张三",18); 36 37 System.out.println(person1.getName()); 38 39 }
6.获取父类的泛型
1 public static void testAnnotation(){ 2 3 //获取带泛型的子类 4 5 Type type=clazz.getGenericSuperclass(); 6 7 System.out.println(type);//entity.Student<entity.Emp> 8 9 //此时获得了泛型参数,然后就是把它提取出来 10 11 //注意Type是一个空的接口,这里使用它的子类ParameterizedType,表示带参数的类类型(即泛型) 12 13 Class clazzs=null; 14 15 if(typeinstanceofParameterizedType){ 16 17 ParameterizedType parameterizedType=(ParameterizedType)type; 18 19 Type[] actualTypeArguments=parameterizedType.getActualTypeArguments(); 20 21 for(Typetypes:actualTypeArguments){ 22 23 System.out.println(types); 24 25 clazzs=(Class<?>)types; 26 27 } 28 29 } 30 31 System.out.println(clazzs); 32 33 }