前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

反射

作者头像
晚上没宵夜
发布2022-05-09 21:06:13
2880
发布2022-05-09 21:06:13
举报
文章被收录于专栏:Howl同学的学习笔记

1. 反射

定义:程序在运行状态中,对于任意一个类,都可以知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意方法和属性

加载流程:假设我们写了一个User类,这个User类加载进内存jvm会为这种类创建唯一的对应的Class类实例,注意这里的Class是一个类型,所有User类都共享同一个对应的Class类,这个Class类包含包名,类名,属性,方法等种种信息

2.Class类

获取Class有三种方法

代码语言:javascript
复制
Class cls = User.class;				//通过类名.class

Class cls = user.getClass();		//通过实例.getClass()

Class cls = Class.forName("User");	//通过Class.forName("全限定类名")
  • Class实例是唯一的存在,所以上面获取的Class都是同一个。但这注意 instance of 匹配的是本类及其子类,而Class只匹配本类,不包括子类

Class常用方法

方法

解释

newInstance()

创建由此类对象表示的类的新实例

forName(String className)

返回与给定字符串名称的类或接口相关联的类对象

getClassLoader()

返回类的类加载器

getPackage()

获取此类的包

getResourceAsStream(String name)

查找具有给定名称的资源(返回类型为InputStream)

getDeclaredField(Srting name)

反映此表示的类或接口的指定已声明字段类对象

getDeclaredMethod(String name, Class<?>... p)

返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象

getDeclaredConstructor(Class<?>... p)

返回Constructor对象

  • Class.newInstance()只能调用public的无参数构造方法

3. Field类

获取字段的方法

方法名

解释

getField(String name)

根据字段名获取某个public的field(包括父类)

getDeclaredField(String name)

根据字段名获取当前类的某个field(不包括父类)

getFields()

获取所有public的field,返回数组(包括父类)

getDeclaredFields()

获取当前类的所有field,返回数组(不包括父类)

  • 其中,没有Declared的能获取父类,本类public的field,而有Declared的只能访问本类的所有field

字段常用方法

方法

解释

get(Object obj)

返回该所表示的字段的值Field ,指定的对象上

set(Object obj, Object value)

将指定对象参数上的此 Field对象表示的字段设置为指定的新值

getName()

返回由此Field对象表示的字段的名称

getType()

返回一个 类对象标识了此表示的字段的声明类型 Field对象

getModifiers()

返回由该 Field对象表示的字段的Java语言修饰符,作为整数

操作(这里准备了UserExtends类)

代码语言:javascript
复制
public class UserExtends {
	
	private int id = 1;
	public String email;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
}

具体操作

代码语言:javascript
复制
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
	
	Class cls = UserExtends.class;
	
	//可以获取字段
	System.out.println(cls.getDeclaredField("id"));
	
	System.out.println("----------------------------------");
	
	//可以获取字段的名字,类型,修饰符
	Field f = cls.getDeclaredField("id");
	System.out.println(f.getName());
	System.out.println(f.getType());
	int m = f.getModifiers();
	System.out.println(Modifier.isPrivate(m)); //Modifiers是一个类,不同数值代表不同修饰符
	
	System.out.println("-------------------------------------");
	
	//获取私有字段的值,需要改变一些方法 1. 字段改为public 2.用f.setAccessible(true);
	//SecurityManager,可以防止private属性访问,所以不用说设置private包装那有什么用了
	f.setAccessible(true);
	
	UserExtends ue = new UserExtends();
	ue.setId(2);
	
	//获取参数对象的字段值
	Object value = f.get(ue);
	System.out.println(value);
	
	//修改参数对象的字段值
	f.set(ue, 3);
	System.out.println(ue.getId());
}

输出

代码语言:javascript
复制
private int reflectionfield.UserExtends.id
----------------------------------
id
int
true
-------------------------------------
2
3

4. Method

获取方法的方法

方法

解释

getMethod(name, Class...)

获取某个public的Method(包括父类)

getDeclaredMethod(name, Class...)

获取当前类的某个Method(不包括父类)

getMethods()

获取所有public的Method(包括父类)

getDeclaredMethods()

获取当前类的所有Method(不包括父类)

常用方法

方法

解释

getName()

返回方法名称

getReturnType()

返回方法返回值类型

getParameterTypes()

返回方法的参数类型

getModifiers()

返回方法的修饰符,返回一个整形

invoke(Object obj, Object... args)

在具有指定参数的 方法对象上调用此 方法对象表示的底层方法

操作(准备了PersonExtends类,里面有两个方法)

代码语言:javascript
复制
public class PersonExtends extends Person{
	
	public int getScore(String type) {
        return 99;
    }
    private int getGrade(int year) {
        return 1;
    }
}
代码语言:javascript
复制
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
	
    //获取类类型
	Class cls = PersonExtends.class;
	
	//获取方法,第一个参数为方法名,第二个为参数类型的类类型
	System.out.println(cls.getDeclaredMethod("getGrade", int.class));
	
	//方法的基本信息
	Method md = cls.getDeclaredMethod("getGrade", int.class);	
	md.getName();
	md.getReturnType();
	md.getParameters();  //返回的是Class数组
	md.getModifiers();
	
	//invoke第一个参数是实例对象,对二个填写参数,就是正常调用时方法的参数
    PersonExtends ps = new PersonExtends();
	System.out.println( md.invoke(ps,123) );
	
	// 静态方法,第一个参数对象就写null
	Method med = Integer.class.getMethod("parseInt", String.class);
	System.out.println( med.invoke(null, "123"));
	
	//本类的私有方法
	//m.setAccessible(true);
	//任然遵循多态,反射父类方法,方法传入子类对象,调用的是子类方法
}
代码语言:javascript
复制
private int reflectionmethod.PersonExtends.getGrade(int)
1
123
  • 方法支持多态,反射父类方法,方法传入子类对象,调用的是子类方法

5. Constructor

获取构造方法也是那四种,就不写了

操作(准备了User类,里面含有无参及有参构造函数)

代码语言:javascript
复制
public class User {
	
	public int id = 1;
	public String name = "Howl";
	
	public User(){
	}
	
	public User(int id, String name) {
		this.id = id;
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
代码语言:javascript
复制
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
	
	//Class的newInstance只支持public的无参构造函数
	User user = User.class.newInstance();
	System.out.println(user.getId());
	System.out.println(user.getName());
	
	//与Method不同,这里的Constructor直接返回一个实例对象
    //参数直接填写参数的类类型,实现重载
	Constructor  cst =  User.class.getConstructor(int.class,String.class);
	User user1 = (User) cst.newInstance(2,"Howlet");
	System.out.println(user1.getId());
	System.out.println(user1.getName());
}
代码语言:javascript
复制
1
Howl
2
Howlet
  • 构造函数不支持多态,只能调用本类的构造函数

6. 反射实现动态代理

在编译时期不写接口的实现类,反而在运行时期创建接口的实例,这就叫做动态代理

interface类型的变量总是通过向上转型并指向某个实例,在反射中有体现,比如有个接口叫User,某个实现了接口的类叫做UserImp,那么他们转型可以这样写

代码语言:javascript
复制
User user = new UserImp();

具体还可以了解代理模式,请戳这里 代理模式

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 反射
  • 2.Class类
  • 3. Field类
  • 4. Method
  • 5. Constructor
  • 6. 反射实现动态代理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档