一.反射

  反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象。

Class 代表字节码的类,代表类的类
Field 代表属性的类
Method 代表方法的类
Constructor 代表构造方法的类
Annotation 代表注解的类
Package 代表包的类

 

 

 

 

 

 

 

二.Class类

2.1 获取Class对象:必须有意义

    ①通过类名.class的方式来获取对应类的字节码对象

 1 import java.util.List;
 2 
 3 public class ClassDemo {
 4     @SuppressWarnings("rawtypes")
 5     public static void main(String[] args)  {
 6 
 7         // 每一个Class对象对应了一个实际的类,因此要求每一个Class都必须有意义
 8         // 如果允许随意创建Class对象,就会导致Class对象没有实际对应的类
 9         // Class clz0 = new Class();
10         
11         // 通过类名.class的方式来获取一个字节码对象
12         // clz表示的就是String的字节码
13         Class<String> clz = String.class;
14         System.out.println(clz);
15 
16         // clz2表示的就是List的字节码
17         Class<List> clz2 = List.class;
18         System.out.println(clz2);
19         
20         // clz3表示的就是String[]的字节码
21         Class<String[]> clz3 = String[].class;
22         System.out.println(clz3);
23         
24     }
25 }
类名.class

 

    ②通过对象.getClass()方法来获取这个对象对应的实际类的字节码对象

 1 public class ClassDemo {
 2     @SuppressWarnings("unchecked")
 3     public static void main(String[] args)  {
 4         Object str = "abc";
 5         Class<String> clz = (Class<String>) str.getClass();
 6         System.out.println(clz);
 7     }
 8 }
 9 
10 //输出:class java.lang.String
对象.getClass()

 

    ③通过Class.forName(类的全路径名)的方法来获取指定类的字节码对象

 1 import java.util.List;
 2 
 3 public class ClassDemo {
 4     @SuppressWarnings("unchecked")
 5     public static void main(String[] args) throws ClassNotFoundException  {
 6         Class<String> clz = (Class<String>) Class.forName("java.lang.String");
 7         System.out.println(clz);
 8         
 9         Class<List> clz2 = (Class<List>) Class.forName("java.util.List");
10         System.out.println(clz2);
11     }
12 }
13 
14 //输出:
15 //class java.lang.String
16 //interface java.util.List
Class.forName(类的全路径名)

 

 

2.2创建由此对象表示的类的新实例

2.2.1 newInstance

字节码对象.newInstance();

 

用处之举例:

    Cat和Dog都实现了Animal接口,利用向上造型,将字符串利用Properties进行更改,可实现任意创建Cat对象或者Dog对象。

 1 public class TestClassDemo {
 2     @SuppressWarnings("unchecked")
 3     public static void main(String[] args) throws Exception {
 4 
 5         // 表示获取了Animal类对应的字节码
 6         //"cn.hdu.reflection.Cat"可以用Properties进去获取
 7         Class<Animal> clz = (Class<Animal>) Class.forName("cn.hdu.reflection.Cat");
 8         
 9         // 要求类中必须有无参构造
10         Animal a = clz.newInstance(); //产生对象
11         System.out.println(a);
12 
13     }
14 
15 }
16 
17 interface Animal {
18 }
19 
20 class Dog implements Animal {
21 
22     @Override
23     public String toString() {
24         return "Dog";
25     }
26 
27 }
28 
29 class Cat implements Animal {
30 
31     @Override
32     public String toString() {
33         return "Cat";
34     }
35 
36 }
AnimalCatDog

 

2.2.2 通过构造方法创建新实例

//只能获取public构造方法
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)  

//不区分是否是public的构造方法
Constructor<?>[] getDeclaredConstructors()  
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  
//需要用 Constructor对象.setAccessible(true);进行设置

 

举例:

 1 import java.lang.reflect.Constructor;
 2 
 3 public class ClassGetConstructorDemo {
 4     public static void main(String[] args) throws Exception {
 5 
 6         // clz代表String类的字节码
 7         Class<String> clz = String.class;
 8 
 9         // String(String)
10         // 只能获取public修饰的构造方法
11         Constructor<String> constructorPublic = clz.getConstructor(String.class);
12         String str = constructorPublic.newInstance("abc");
13         System.out.println(str);
14 
15          // String(byte[], int, int)
16         Constructor<String> constructorParameters = clz.getConstructor(byte[].class, int.class, int.class);
17         String str2 = constructorParameters.newInstance(new byte[] { 97, 98, 99, 100 }, 1, 3);
18         System.out.println(str2);
19 
20         // 获取指定的构造方法,不区分是否是public的
21         Constructor<String> constructorPrivate = clz.getDeclaredConstructor(char[].class, boolean.class);
22         // 暴力破解/暴力拆除
23         constructorPrivate.setAccessible(true);
24         String str3 = constructorPrivate.newInstance(new char[] { 'a', 'b', 'c' }, true);
25         System.out.println(str3);
26     }
27 
28 }
getConstructor

在String源码中是默认的,非public

 

2.3 获取方法

//public
Method getMethod(String name, 类<?>... parameterTypes)  
Method[] getMethods()  //获取所有公有方法(包含了父类的方法也包含Object类) 

//非public
Method getDeclaredMethod(String name, 类<?>... parameterTypes) 
Method[] getDeclaredMethods() //获取所有的成员方法,包括私有的(不包括继承的)
//m.setAccessible(true);

//使用所指定的方法:Method的对象.invoke(Object obj, Object... args);

 

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Method;
 3 
 4 public class ClassGetMethodDemo {
 5 
 6     public static void main(String[] args) throws Exception {
 7 
 8         Class<String> clz = String.class;
 9 
10         // 表示String(String)
11         Constructor<String> c = clz.getConstructor(String.class);
12         String str = c.newInstance("abcdefg");
13 
14         // 获取charAt(int)
15         // 只能获取public修饰的方法
16         Method m = clz.getMethod("charAt", int.class);
17         // 执行方法对象
18         // 相当于char ch = str.charAt(3);
19         char ch = (char) m.invoke(str, 3);
20         System.out.println(ch);
21 
22         // 获取指定的方法
23         Method m2 = clz.getDeclaredMethod("lastIndexOfSupplementary", int.class, int.class);
24         m2.setAccessible(true);
25         int i = (int) m2.invoke(str, 2, 3);
26         System.out.println(i);    
27     }
28 
29 }
getMethod

 

 

2.4 获取属性

//public
Field getField(String name)  
Field[] getFields()  

//非public
Field getDeclaredField(String name)  
Field[] getDeclaredFields()  
//f.setAccessible(true);

//Field类
获取:Object get(Object obj) 
设置:void set(Object obj, Object value)  
        void setChar(Object obj, char c) 
        void setDouble(Object obj, double d) 
        void setInt(Object obj, int i) 
        ... ...
 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 
 4 public class ClassGetFieldDemo {
 5     public static void main(String[] args) throws Exception {
 6 
 7         Class<String> clz = String.class;
 8 
 9         // 表示String(String)
10         Constructor<String> c = clz.getConstructor(String.class);
11         String str = c.newInstance("abcdefg");
12 
13         // 获取类中指定的属性
14         Field f = clz.getDeclaredField("hash");
15         f.setAccessible(true);
16         System.out.println(f.get(str));
17         // 设置属性的值
18         f.set(str, 125);
19         // 获取属性的值
20         System.out.println(f.get(str));
21     }
22 }
getField

 

 

2.5 获取注解

<A extends Annotation>A getAnnotation(类<A> annotationClass)  
Annotation[] getAnnotations()  

<A extends Annotation>A getDeclaredAnnotation(类<A> annotationClass)  
Annotation[] getDeclaredAnnotations()  

 

 

2.6 Class类其它常用方法

 1 import java.lang.reflect.TypeVariable;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 
 5 public class ClassDemo {
 6 
 7     @SuppressWarnings("rawtypes")
 8     public static void main(String[] args) {
 9 
10         Class<String> clz = String.class;
11 
12         // 获取这个类实现的所有的接口
13         Class[] ins = clz.getInterfaces();
14         for (Class c : ins) {
15             System.out.println(c);
16         }
17 
18         // 获取父类
19         Class superc = clz.getSuperclass();
20         System.out.println(superc);
21 
22         // 获取类的全路径名
23         System.out.println(clz.getName());
24         // 获取类的简称
25         System.out.println(clz.getSimpleName());
26 
27         // 获取所在的包
28         System.out.println(clz.getPackage());
29 
30         List<String> list = new ArrayList<>();
31         Class lclz = list.getClass();
32         TypeVariable[] ts = lclz.getTypeParameters();
33         for (TypeVariable typeVariable : ts) {
34             System.out.println(typeVariable);
35         }
36 
37         // 判断是否是一个枚举
38         System.out.println(clz.isAnnotation());
39         // 判断是否是一个基本类型
40         System.out.println(clz.isPrimitive());
41 
42         // 判断参数是否是指定类型的实例的
43         Object str = "abc";
44         System.out.println(clz.isInstance(str));
45         System.out.println(str instanceof String);
46 
47         // 判断两个类之间是否有继承关系
48         System.out.println(Object.class.isAssignableFrom(String.class));
49 
50     }
51 
52 }

 

posted on 2018-03-06 20:04  kuotian  阅读(266)  评论(0编辑  收藏  举报