为什么使用反射
比如某公司定义了一组接口,然后第三方公司按照这个公司的接口实现了一套功能,然后交给这个公司,但是这个公司的项目已经结束,如何实现动态加载第三方公司提供的功能。
什么是反射
反射就是把Java类中的各种成分映射成一个个的Java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
反射常用类
- Class类—可获取类和类的成员信息
- Field类—可访问类的属性
- Method类—可调用类的方法
- Constructor类—可调用类的构造方法
使用反射的步骤
1.导入java.lang.reflect.*
2.获得需要操作的类的Java.lang.Class对象
3.调用Class的方法获取Field、Method等对象
4.使用反射API进行操作(设置属性﹑调用方法)
Class类
Class类是反射的起源和入口
- 每个类都有自己的Class对象
- 提供了获取类信息的相关方法
- Class类继承自Object类
Class类存储类的结构信息
- 类名
- 父类﹑接口
- 方法﹑构造方法﹑属性
- 注释
获取Class对象的方法
1.类名.getClass
//方法1:对象.getClass()
Student stu=new Student();
Class clazz=stu.getClass();
2.类名.Class
//方法2:类.class
clazz= Student.class;
clazz=String.class;
3.Class.forname(“stu”);推荐这种方法,耦合度低
//方法3:Class.forName()
clazz=Class.forName("java.lang.String");
clazz=Class.forName("java.util.Date");
获取类的其他信息
Class clazz = Class.forName("java.lang.Object");
Field fields[ ] = clazz.getDeclaredFields();//获取Field 对象 属性
Method methods[] = clazz.getDeclaredMethods();//获取Method 对象 方法
Constructor constructors[] = clazz.getDeclaredConstructors();//获取Constructor对象 构造方法
动态创建对象方法
1.使用Class的newInstance()方法,仅限于无参构造
Class clazz=Class.forName("com.qf.reflection.Student");
Object obj=clazz.newInstance();
2.使用Constructor方法的newInstance()方法,适用于所有构造方法
Constructor cons = clazz.getConstructor(new Class[]{ String.class, int.class, float.class });
Object obj = cons.newInstance(new Object[ ] {"lkl", 32, 56.5f });
通过反射获取类的各种信息:
类:
package com.qf;
/*
* wgy 2019/8/16 9:55
* 佛祖保佑,永无BUG!
*/
public class Person extends AbstractPerson<String> implements Comparable<String>{
//成员变量
private String name;
private int age;
private String gender;
//构造方法
public Person() {
}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//方法
//无参无返回值
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
}
//有参无返回值
public void show(String address){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender+" 地址:"+address);
}
//带返回值的方法
public String getInfo(){
return "信息:"+name+" "+age+" "+gender;
}
//静态方法
public static void print(){
System.out.println("这是一个静态方法");
}
//私有方法
private void show(String address,String email){
System.out.println("地址:"+address+" 邮箱:"+email);
}
@Override
public int compareTo(String o) {
return 0;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
反射获得信息
package com.qf;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/*
* 使用反射技术操作Person
* (1)获取类的类对象
* (2)获取类中构造方法
* (3)获取方法
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// getClazz();
//getConstructor();
// getMethod();
getField();
}
//(1)获取类的类对象
public static void getClazz() throws Exception{
//方式1:使用class属性获取
Class<?> clazz1=Person.class;
System.out.println(clazz1.hashCode());
//方法2 使用getClass方法
Person shaobo=new Person();
Class<?> clazz2 = shaobo.getClass();
System.out.println(clazz2.hashCode());
//方式3 使用Class.forName方法:耦合性低,不依赖于具体的类,可以编译通过
Class<?> clazz3=Class.forName("com.qf.Person");
System.out.println(clazz3.hashCode());
//扩展
//获取父类
Class<?> superclass = clazz3.getSuperclass();
System.out.println(superclass.getName());
//获取父类泛型
Type genericSuperclass = clazz3.getGenericSuperclass();
System.out.println(genericSuperclass.getTypeName());
//获取接口
Class<?>[] interfaces = clazz3.getInterfaces();
System.out.println(interfaces.length);
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface.toString());
}
//获取包名
Package aPackage = clazz3.getPackage();
System.out.println(aPackage.getName());
}
public static void getConstructor() throws Exception{
Class<?> clazz=Class.forName("com.qf.Person");
//1获取构造方法
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("--------------------------");
//2获取单个构造方法
//2.1获取无参构造方法
Constructor<?> constructor = clazz.getConstructor();
//2.2获取带参
Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
System.out.println(constructor);//输出的是Person 的无参构造方法
System.out.println(constructor1);//输出的是Person的有参构造方法,包括参数所在的包
//3利用构造方法创建对象
System.out.println("---------利用构造方法创建对象------------");
Person zhangsan=new Person();
Object lisi = constructor.newInstance();
System.out.println(zhangsan);
System.out.println(lisi);
Object wangwu = constructor1.newInstance("王五", 20, "男");
System.out.println(wangwu);
//简单创建对象的方法
Object o = clazz.newInstance();
System.out.println(o.toString());
}
//获取方法
public static void getMethod() throws Exception{
//1获取无参的方法
Class<?> clazz=Class.forName("com.qf.Person");
//Method[] methods = clazz.getMethods();//获取公类自己公开的方法,继承的公开方法
// Method[] methods = clazz.getDeclaredMethods();//获取公类自己所有的方法,包括非公开的方法
// System.out.println("-----------getMethods();----------");
// for (Method method : methods) {
// System.out.println(method);
// }
// Person p=new Person();
// p.show();
Object zhangsan = clazz.newInstance();
Method show = clazz.getMethod("show");
show.invoke(zhangsan);// zhangsan.show();
//2获取有参
Method show2=clazz.getMethod("show",String.class);
show2.invoke(zhangsan, "北京");
//3获取带返回值的方法
Method getInfo = clazz.getMethod("getInfo");
Object value=getInfo.invoke(zhangsan);
System.out.println(value);
//4获取静态方法
Method print = clazz.getMethod("print");
print.invoke(null);// Person.print();
//5私有方法
Method show3 = clazz.getDeclaredMethod("show", String.class, String.class);
//设置访问权限无效
show3.setAccessible(true);
show3.invoke(zhangsan, "上海","zhangsan@qq.com");
}
public static void getField() throws Exception{
//1获取类对象
Class<?> clazz = Class.forName("com.qf.Person");
//2获取
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取单个
System.out.println("--------------------------");
Field name = clazz.getDeclaredField("name");
//
// Person wangwu=new Person();
// wangwu.name="王五";
Object wangwu = clazz.newInstance();
//赋值
name.setAccessible(true);
name.set(wangwu, "王五");// wangwu.name="王五";
//获取
Object object=name.get(wangwu);// wangwu.name
System.out.println(object);
}
}