java反射学习笔记
1、java反射概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
JAVA反射机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
2、Class类
Class类用于表示一个.class文件,通过这个类的Class对象可以反射出该类的字段、方法、构造函数、注释等等。任何数据类型都有自己的Class对象。
获得Class对象的方式有三种:
1 package reflect; 2 3 public class Dog { 4 5 public static void main(String[] args) throws Exception { 6 //1、 7 Class clazz1 = Class.forName("reflect.Dog"); 8 System.out.println(clazz1.getName()); 9 10 //2、 11 Class clazz2 = Dog.class; 12 System.out.println(clazz2.getName()); 13 14 //3、 15 Class clazz3 = new Dog().getClass(); 16 System.out.println(clazz3.getName()); 17 } 18 19 }
运行结果:
reflect.Dog
reflect.Dog
reflect.Dog
3、Constructor类
Constructor
提供关于类的单个构造方法的信息以及对它的访问权限。Constructor
类的实例对象代表一个类的构造方法。
3.1、得到某个类所有的构造方法,例:
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
3.2、得到某一个构造方法,例:
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
3.3、利用构造方法创建实例对象:
String str = (String)constructor.newInstance(“abc”);
3.4、Class类的newInstance()方法也可创建类的实例,其内部工作原理是先得无参的构造方法,再用构造方法创建实例对象。
String obj =(String)Class.forName("java.lang.String").newInstance();
1 package reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 public class Dog { 8 private int id; 9 private String name; 10 private List list; 11 12 private Dog(List list) { 13 this.list = list; 14 System.out.println("反射私有构造函数"); 15 } 16 17 public Dog() { 18 System.out.println("dog"); 19 } 20 21 public Dog(String name) { 22 this.name = name; 23 } 24 25 public Dog(String name, int id) { 26 this.name = name; 27 this.id = id; 28 } 29 30 public int getId() { 31 return id; 32 } 33 34 public void setId(int id) { 35 this.id = id; 36 } 37 38 public String getName() { 39 return name; 40 } 41 42 public void setName(String name) { 43 this.name = name; 44 } 45 46 public static void main(String[] args) throws Exception { 47 48 Class clazz = Class.forName("reflect.Dog"); 49 //得到某个类所有的构造方法 50 Constructor[] Constructors = clazz.getConstructors(); 51 52 //反射无参构造方法 53 Constructor c1 = clazz.getConstructor(null); 54 Dog d = (Dog) c1.newInstance(null); 55 56 //反射Dog(String name)构造函数 57 Constructor c2 = clazz.getConstructor(String.class); 58 Dog d2 = (Dog) c2.newInstance("guoguo"); 59 System.out.println("d2:"+d2.getName()); 60 61 //反射public Dog(String name, int id)构造函数 62 Constructor c3 = clazz.getConstructor(String.class, int.class); 63 Dog d3 = (Dog) c3.newInstance("guoguo",12); 64 System.out.println("d3:"+d3.getId()+"--"+d3.getName()); 65 66 //反射private Dog(List list)构造函数 67 Constructor c4 = clazz.getDeclaredConstructor(List.class); 68 c4.setAccessible(true); 69 Dog d4 = (Dog) c4.newInstance(new ArrayList()); 70 71 //或者通过class.newIntance获取对象 72 Dog d5 = (Dog) clazz.newInstance(); 73 } 74 }
运行结果:
dog
d2:guoguo
d3:12--guoguo
反射私有构造函数
dog
3、Field类
Field
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
1 package reflect; 2 3 import java.lang.reflect.Field; 4 import java.util.List; 5 6 public class Dog { 7 private int id; 8 private String name; 9 private List list; 10 11 private Dog(List list) { 12 this.list = list; 13 System.out.println("反射私有构造函数"); 14 } 15 16 public Dog() { 17 System.out.println("dog"); 18 } 19 20 public Dog(String name) { 21 this.name = name; 22 } 23 24 public Dog(String name, int id) { 25 this.name = name; 26 this.id = id; 27 } 28 29 public int getId() { 30 return id; 31 } 32 33 public void setId(int id) { 34 this.id = id; 35 } 36 37 public String getName() { 38 return name; 39 } 40 41 public void setName(String name) { 42 this.name = name; 43 } 44 45 public static void main(String[] args) throws Exception { 46 47 Class clazz = Class.forName("reflect.Dog"); 48 49 //获取所有成员变量 50 Field[] fs = clazz.getDeclaredFields(); 51 for (Field f : fs) { 52 System.out.println(f.getName()); 53 } 54 55 //private String name; 给变量赋值 56 Dog d1 = new Dog(); 57 Field f1 = clazz.getDeclaredField("name"); 58 f1.setAccessible(true); 59 f1.set(d1, "guoguo"); 60 System.out.println(); 61 System.out.println("d1:"+d1.getName()); 62 63 //获取变量的值 64 Dog d2 = new Dog("guoguo"); 65 Field f2 = clazz.getDeclaredField("name"); 66 f2.setAccessible(true); 67 System.out.println(); 68 System.out.println("d2:"+f2.get(d2)); 69 } 70 }
运行结果:
id
name
list
dog
d1:guoguo
d2:guoguo
4、Method类
Method
提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反射的方法可能是类方法或实例方法(包括抽象方法)。
得到类中的某一个方法:
例子: Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式: System.out.println(charAt.invoke(str, 1));
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法!
1 package reflect; 2 3 import java.lang.reflect.Method; 4 5 public class Dog { 6 7 public void run() { 8 System.out.println("run1..."); 9 } 10 11 public void run(String str) { 12 System.out.println("run2...."); 13 } 14 public void run(String str1, String[] str2, int[] id) { 15 System.out.println("run3...."); 16 } 17 18 private void say() { 19 System.out.println("say.."); 20 } 21 22 private String say(String str) { 23 return str; 24 } 25 26 public static void eat() { 27 System.out.println("eat..."); 28 } 29 30 public static void main(String[] args) throws Exception { 31 Class clazz = Class.forName("reflect.Dog"); 32 Dog d = (Dog) clazz.newInstance(); 33 34 //反射public void run() 35 Method run1 = clazz.getMethod("run",null); 36 run1.invoke(d,null); 37 38 //反射public void run(String str) 39 Method run2 = clazz.getMethod("run",String.class); 40 run2.invoke(d, "str1"); 41 42 //反射public void run(String str1,String str2) 43 Method run3 = clazz.getMethod("run",String.class,String[].class,int[].class); 44 run3.invoke(d, "str", new String[]{"1","2"},new int[]{1}); 45 46 //反射私有方法private void say() 47 Method say = clazz.getDeclaredMethod("say", null); 48 say.setAccessible(true); 49 say.invoke(d, null); 50 51 //反射带返回值的方法private String say(String str) 52 Method say2 = clazz.getDeclaredMethod("say", String.class); 53 say2.setAccessible(true); 54 String result = (String) say2.invoke(d, "aaa..."); 55 System.out.println(result); 56 57 //反射静态方法 58 Method eat = clazz.getMethod("eat", null); 59 eat.invoke(null, null); //null 60 61 } 62 }
运行结果:
run1...
run2....
run3....
say..
aaa...
eat...