Class对象:
Class对象记录了所有与类相关的信息,当类加载器从文件系统中加载.class文件到JVM中的同时会为每一个类创建一个Class对象。通过Class对象可以获取到类的属性、方法、构造器等全部与类相关的信息。
现在假设在com.aop包下有一个抽象类和一个类,定义如下:
package com.aop; abstract public class Creature<T> { }
1 package com.aop; 2 3 public class Person extends Creature<String>{ 4 5 int id; 6 public String name; 7 private int age; 8 9 public Person() { } 10 public Person(int age, String name){ 11 this.age = age; 12 this.name = name; 13 } 14 15 public int getId() { 16 return id; 17 } 18 19 public void setId(int id) { 20 this.id = id; 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public int getAge() { 28 return age; 29 } 30 31 public void setName(String name) { 32 this.name = name; 33 } 34 35 public void setAge(int age) { 36 this.age = age; 37 } 38 39 static public void countAdd(int a, Integer b){ 40 System.out.println(a + " + " + b + " = " + (a+b)); 41 } 42 43 public void show() { 44 System.out.println("我是一个人!"); 45 } 46 47 public void display(String nation) { 48 System.out.println("我的国际是:" + nation); 49 } 50 51 @Override 52 public String toString() { 53 return "Person [name=" + name + ", age=" + age + "]"; 54 } 55 56 }
很简洁,定义一个带泛型的抽象类,Person继承自该抽象类。
与反射相关的包:
import java.lang.reflect.Constructor; //与构造器相关
import java.lang.reflect.Field; //与域相关
import java.lang.reflect.Method; //与方法相关
//还有其它的...
1、Class对象的4中获取方式:
1 package com.aop; 2 3 import org.junit.Test; 4 5 public class TestReflection { 6 7 @Test 8 public void testReflection() throws Exception{ 9 10 //1.调用运行时类本身的.class属性 11 Class<Person> clazz1 = Person.class; 12 13 //2.通过运行时类的对象获取 14 Person person = new Person(); 15 Class<? extends Person> clazz2 = person.getClass(); 16 17 //3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。 18 String className = "com.aop.Person"; 19 20 Class<?> clazz3 = Class.forName(className); 21 22 //4.(了解)通过类的加载器 23 ClassLoader loader = this.getClass().getClassLoader(); 24 Class<?> clazz4 = loader.loadClass(className); 25 26 System.out.println(clazz1.getName()); 27 System.out.println(clazz2.getName()); 28 System.out.println(clazz3.getName()); 29 System.out.println(clazz4.getName()); 30 31 System.out.println(clazz1 == clazz2); 32 System.out.println(clazz1 == clazz3); 33 System.out.println(clazz1 == clazz4); 34 } 35 }
2、通过反射读取对象的属性值,并修改它们(能够读取与修改包括private权限的属性值)
1 @Test 2 public void testField() throws Exception{ 3 String className = "com.aop.Person"; 4 Class<?> clazz = Class.forName(className); 5 6 Person person = (Person) clazz.newInstance(); 7 8 //getField(...)方法会获取public类型的属性,包括父类的public类型属性都能获取 9 Field field = clazz.getField("name"); 10 field.set(person, "东东"); 11 System.out.println(person); 12 13 //getDeclaredField(...)获取所有所有类型的属性,但是,不包括父类的属性在内 14 Field field2 = clazz.getDeclaredField("age"); 15 //如果类中的属性设定为private或者是“默认类型”,则需要设置其可访问属性 16 field2.setAccessible(true); 17 field2.set(person, 100); 18 System.out.println(person); 19 20 }
3、通过反射调用对象的方法
1 @Test 2 public void testMethod() throws Exception{ 3 String className = "com.aop.Person"; 4 Class<?> clazz = Class.forName(className); 5 6 Person person = new Person(50, "哈哈"); 7 8 //获取并调用无参的show方法 9 Method method1 = clazz.getMethod("show"); 10 method1.invoke(person); 11 12 //获取并调用有参的display方法 13 Method method2 = clazz.getMethod("display", String.class); 14 method2.invoke(person, "中国"); 15 16 //调用有返回值的方法 17 Method method3 = clazz.getMethod("toString"); 18 Object resultVal = method3.invoke(person); 19 System.out.println(resultVal); 20 21 //调用有参数的静态方法 22 Method method4 = clazz.getMethod("countAdd", int.class, Integer.class); 23 method4.invoke(Person.class, 10, 100); 24 }
4、通过反射调用带参构造器来实例化一个对象
1 @Test 2 public void testConstructor() throws Exception{ 3 String className = "com.aop.Person"; 4 Class<?> clazz = Class.forName(className); 5 6 //调用一个有参的构造器 7 Constructor<?> cons = clazz.getConstructor(int.class, String.class); 8 Person person = (Person) cons.newInstance(20, "兮兮"); 9 System.out.println(person); 10 }
5、获取“父类”、“带泛型的父类”、“父类的泛型”
1 @Test 2 public void testGeneric() throws Exception{ 3 String className = "com.aop.Person"; 4 Class<?> clazz = Class.forName(className); 5 6 //1、获取父类,只能得到父类的名称 7 Class<?> superClazz = clazz.getSuperclass(); 8 System.out.println(superClazz); 9 10 //2、获取带泛型的父类 11 Type type = clazz.getGenericSuperclass(); 12 System.out.println(type); 13 14 //3、获取父类的泛型类(重要) 15 ParameterizedType param = (ParameterizedType)type; 16 Type[] argmts = param.getActualTypeArguments(); 17 Class<?> claz = (Class<?>)argmts[0]; 18 System.out.println(claz); 19 }
下面是全部的源代码:
1 package com.aop; 2 3 abstract public class Creature<T> { 4 5 }
1 package com.aop; 2 3 public class Person extends Creature<String>{ 4 5 int id; 6 public String name; 7 private int age; 8 9 public Person() { } 10 public Person(int age, String name){ 11 this.age = age; 12 this.name = name; 13 } 14 15 public int getId() { 16 return id; 17 } 18 19 public void setId(int id) { 20 this.id = id; 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public int getAge() { 28 return age; 29 } 30 31 public void setName(String name) { 32 this.name = name; 33 } 34 35 public void setAge(int age) { 36 this.age = age; 37 } 38 39 static public void countAdd(int a, Integer b){ 40 System.out.println(a + " + " + b + " = " + (a+b)); 41 } 42 43 public void show() { 44 System.out.println("我是一个人!"); 45 } 46 47 public void display(String nation) { 48 System.out.println("我的国际是:" + nation); 49 } 50 51 @Override 52 public String toString() { 53 return "Person [name=" + name + ", age=" + age + "]"; 54 } 55 56 }
1 package com.aop; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Field; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.ParameterizedType; 7 import java.lang.reflect.Type; 8 9 import org.junit.Test; 10 11 public class TestReflection { 12 13 @Test 14 public void testReflection() throws Exception{ 15 16 //1.调用运行时类本身的.class属性 17 Class<Person> clazz1 = Person.class; 18 19 //2.通过运行时类的对象获取 20 Person person = new Person(); 21 Class<? extends Person> clazz2 = person.getClass(); 22 23 //3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。 24 String className = "com.aop.Person"; 25 26 Class<?> clazz3 = Class.forName(className); 27 28 //4.(了解)通过类的加载器 29 ClassLoader loader = this.getClass().getClassLoader(); 30 Class<?> clazz4 = loader.loadClass(className); 31 32 System.out.println(clazz1.getName()); 33 System.out.println(clazz2.getName()); 34 System.out.println(clazz3.getName()); 35 System.out.println(clazz4.getName()); 36 37 System.out.println(clazz1 == clazz2); 38 System.out.println(clazz1 == clazz3); 39 System.out.println(clazz1 == clazz4); 40 } 41 42 @Test 43 public void testField() throws Exception{ 44 String className = "com.aop.Person"; 45 Class<?> clazz = Class.forName(className); 46 47 Person person = (Person) clazz.newInstance(); 48 49 //getField(...)方法会获取public类型的属性,包括父类的public类型属性都能获取 50 Field field = clazz.getField("name"); 51 field.set(person, "东东"); 52 System.out.println(person); 53 54 //getDeclaredField(...)获取所有所有类型的属性,但是,不包括父类的属性在内 55 Field field2 = clazz.getDeclaredField("age"); 56 //如果类中的属性设定为private或者是“默认类型”,则需要设置其可访问属性 57 field2.setAccessible(true); 58 field2.set(person, 100); 59 System.out.println(person); 60 61 } 62 63 @Test 64 public void testMethod() throws Exception{ 65 String className = "com.aop.Person"; 66 Class<?> clazz = Class.forName(className); 67 68 Person person = new Person(50, "哈哈"); 69 70 //获取并调用无参的show方法 71 Method method1 = clazz.getMethod("show"); 72 method1.invoke(person); 73 74 //获取并调用有参的display方法 75 Method method2 = clazz.getMethod("display", String.class); 76 method2.invoke(person, "中国"); 77 78 //调用有返回值的方法 79 Method method3 = clazz.getMethod("toString"); 80 Object resultVal = method3.invoke(person); 81 System.out.println(resultVal); 82 83 //调用有参数的静态方法 84 Method method4 = clazz.getMethod("countAdd", int.class, Integer.class); 85 method4.invoke(Person.class, 10, 100); 86 } 87 88 @Test 89 public void testConstructor() throws Exception{ 90 String className = "com.aop.Person"; 91 Class<?> clazz = Class.forName(className); 92 93 //调用一个有参的构造器 94 Constructor<?> cons = clazz.getConstructor(int.class, String.class); 95 Person person = (Person) cons.newInstance(20, "兮兮"); 96 System.out.println(person); 97 } 98 99 @Test 100 public void testGeneric() throws Exception{ 101 String className = "com.aop.Person"; 102 Class<?> clazz = Class.forName(className); 103 104 //1、获取父类,只能得到父类的名称 105 Class<?> superClazz = clazz.getSuperclass(); 106 System.out.println(superClazz); 107 108 //2、获取带泛型的父类 109 Type type = clazz.getGenericSuperclass(); 110 System.out.println(type); 111 112 //3、获取父类的泛型类(重要) 113 ParameterizedType param = (ParameterizedType)type; 114 Type[] argmts = param.getActualTypeArguments(); 115 Class<?> claz = (Class<?>)argmts[0]; 116 System.out.println(claz); 117 } 118 119 }
参考:尚硅谷java视频