1.反射的基本概念
一般情况下,知道一个类,可以通过这个类创建对象;但是如果要求通过一个对象找到一个类,这时候反射就派上用场了。java反射实现的核心就是 java.lang包下的Class类
2.Class类的基本使用
(1)通过Class类获取对象完整包类名
新建一个Student类
public class Student {
}
然后写一个测试类
public class test11 {
public static void main(String[] args) {
Student s=new Student();
System.out.println(s.getClass().getName());
}
}
运行结果
这里对象.getClass() 调用的是Object类的getClass() 得到Class对象 然后再调用Class里的getName()方法,获取到完整包路径类
(2)通过完整包路径类型来实例化Class对象
public class test12 {
public static void main(String[] args) {
try {
Class<?>c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果
通过得到Class对象,我们可以通过Class对象得到Test2.Student类的完整结构;
(3)通过完整包路径类型来实例化Class对象,再通过Class对象获取Student类实例
先改写下Student类
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [name="+this.name+", age="+this.age+"]";
}
}
再写个测试类
public class test13 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Student s=null;
try {
s=(Student) c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s.setName("小明");
s.setAge(18);
System.out.println(s.toString());
}
}
运行结果
我们再Student 类中加下有参构造方法,这样使得Student类没有默认无参构造方法
我们再运行上面的测试类,运行结果如下
报错了 找不到默认构造方法,在这种情况下,我们可以通过Class类来获取Student类里的构造方法,再调用构造方法即可,我们前面说过,可以通过反射获取整个类的结构,包括 属性 方法 构造方法 等等
再写个测试类
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class test14 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Student s=null;
Constructor<?>[] cons=c.getConstructors();//通过反射获取整个类的构造方法
try {
s=(Student) cons[0].newInstance("小明",18);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(s.toString());
}
}
运行结果
2.通过反射获取类的基本结构
过反射获取类的基本结构,下面讲解通过反射获取类的构造方法、普通方法、属性
先改写下Student类,加点方法
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student(String name) {
super();
this.name = name;
}
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我的名字是:"+this.name);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [name="+this.name+", age="+this.age+"]";
}
}
(1)通过getConstructors()方法获取所有构造方法
import java.lang.reflect.Constructor;
public class test15 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?>[] cons=c.getConstructors();//获得所有构造器的数组
//foreach遍历
for (Constructor<?> constructor : cons) {
System.out.println("构造方法:"+constructor);
}
}
}
运行结果
(2)通过getMethods()方法获取(除括构造方法)所有方法,
import java.lang.reflect.Method;
public class test16 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method mds[]=c.getMethods();//获取所有方法
//foreach遍历
for (Method method : mds) {
System.out.println(method);
}
}
}
运行结果
(3)通过getDeclaredFields()方法获取所有属性
import java.lang.reflect.Field;
public class test17 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field fd[]=c.getDeclaredFields();
for (Field field : fd) {
System.out.println(field);
}
}
}
运行结果
3.通过反射调用方法和操作属性
先改下Student类
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void say() {
System.out.println("我的名字是:"+this.name);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student [name="+this.name+", age="+this.age+"]";
}
}
(1)通过反射调用方法,主要通过invoke()方法
import java.lang.reflect.Method;
public class test18 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
Object obj=c.newInstance();
Method m2=obj.getClass().getMethod("setName", String.class);
m2.invoke(obj, "小明");
Method m=obj.getClass().getMethod("getName");
String name=(String) m.invoke(obj);
System.out.println("name="+name);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
(2)通过反射操作属性,java里反射可以操作私有属性,只需要设置下
import java.lang.reflect.Field;
public class test19 {
public static void main(String[] args) {
Class<?>c=null;
try {
c=Class.forName("Test2.Student");
System.out.println(c.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
Object obj=c.newInstance();
Field nameField=c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj, "小明");
System.out.println("name="+nameField.get(obj));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
(4)同理,可通过getInterfaces()方法 和 getSuperclass()方法 分别获取所有实现的接口和父类