在Java中,如何使用一个类。
已知一个类的类名,以及类中的属性,构造方法等。
使用new关键字构造对象,使用对象调用方法或属性。
如果只知道一个类的类名,也可以动态得到类的定义信息,比如属性,方法等。
Java反射
定义:在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用该对象的属性和方法。这种动态获取信息以及动态调用对象的方法称为java语言的反射机制。
作用:动态获取类的信息
Java反射相关API
Java反射相关类主要包括
Class | 类型 |
Constructor | 构造方法 |
Method | 方法 |
Filed | 属性 |
除了Class外,其他类都位于java.lang.reflect包中
反射就是从Class开始
Java反射相关的类
Class类
一旦Class文件被加载到内存,就会为其创建一个Class对象。任何类使用时都会创建一个Class对象。
Class类是Java反射的基础,通过Class类可以得到类的基本信息。
获得Class类的三种方法
要获得类的方法,首先要获得类的实例,常用的三种方法
//通过对象名获取到类的Class对象
User user = new User(1,"6666");
Class c1 = user.getClass();
//通过类名.Class
Class c2 = User.class;
//通过类的地址
Class c3 = Class.forName("com.ffyc.javareflect.User");
获得Constructor类的实例
Constructor可以通过getXxx()方法获得构造方法的基本信息
getName();返回构造方法的名字
Object object = constructor.newInstance(); //通过无参构造方法,创建对象
Filed类的作用
Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也
可以对属性进行赋值.
getName:返回属性的名字
set:设置属性值
Method类
将类中的方法进行封装,可以动态的获取方法的信息。
//获得类中的构造方法
Constructor constructor = c.getDeclaredConstructor();//获得类中的无参构造方法
constructor.setAccessible(true);//设置对私有权限构造方法操作
Object object = constructor.newInstance();//通过无参构造方法,创建对象
Method method = c.getMethod("setId", int.class);
System.out.println(method.getName());// setId
method.invoke(object,100);
System.out.println(object);// User{id=100, name='null'}
反射优缺点
优点:
- 增加程序的灵活性,可以在运行过程中动态对类进行操作和修改
- 提高代码复用率
- 可以在运行时轻松获取任意一个类的方法和属性
缺点:
- 反射会涉及到动态类型的解析,导致性能比非反射更低
- 反射可以绕过一些限制访问的属性和方法,会破坏代码本身的抽象性。
- 反射通常要在一个没有安全限制的程序运行
代码案例
public class User {
private int id;
private String name;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
private User() {
System.out.println("user无参构造方法");
}
public User(int id, String name) {
System.out.println("user有参构造");
this.id = id;
this.name = name;
}
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//通过类的地址
String cname = "com.ffyc.javareflect.User";
Class c = Class.forName(cname);
//获得类中的构造方法
Constructor constructor = c.getDeclaredConstructor();//获得类中的无参构造方法
constructor.setAccessible(true);//设置对私有权限构造方法操作
Object object = constructor.newInstance();//通过无参构造方法,创建对象
Map<String,Object> map = new HashMap<>();
map.put("id",100);
map.put("name","张三");
Field[] fields = c.getDeclaredFields(); //获得所有属性
for (Field f: fields) {
f.setAccessible(true);
f.set(object,map.get(f.getName())); //返回由此 Field对象表示的字段的名称。 类的所有属性名称
System.out.println(f.getName());
}
System.out.println(object);
}