java基础:反射

反射

1、概述

1.1 定义

在运行程序的过程中,动态获取一个类中的基本信息

2、Class类型

2.1 定义

java.lang.Class是API中提供的一个类,可以表示java中所有的类型,包括基本类型和引用类型。

2.2 使用Class类对向表示不同类型

表示基本类型

//对象c表示int类型
CLass c = int.class;
//判断对象c是不是基本类型
System.out.println(c.isPrimitive());
//获取对象c所代表的类型的名字
System.out.println(c.getName());

表示类类型

假设有个Student类

//对象c代表Student类型
Class c = Student.class;
//获取Student类的全限定名
System.out.println(c.getName());

表示接口类型

//对象c表示List接口类型
Class c = List.class;
//判断对象c是不是接口类型
System.out.prinln(c.isInterface());
System.out.println(c.getName());

表示数组类型

Class c;
c = Student[].class;
//判断对象c是不是数组类型
System.out.println(c.isArray());
//获取数组的简单名
System.out.println(c.getSimpleName());
//获取该数组具体类型是什么
System.out.println(c.getComponentType().getSimpleName());

运行结果
true
Student[]
Student

3、获取Class对象的方式

总的来说有下面的三种方式,但不同类型对象使用的方式有些许区别
方式一:使用类型名称直接获取**(最常用)**
方式二:使用Class类中的静态方法forName获取
方式三:使用对象调用getClass方法获取

获取基本类型的Class对象:
只有一种方式:类型名称直接获取

Class c = int.class;

获取接口类型的Class对象:
两种方式:
方式1:类型名称直接获取

Class c = Action.class;

方式2:使用Class类中的静态方法forName获取

Class c = Class.forName("全限定名");

获取数组类型的Class对象:
两种方式:类型名称直接获取
方式1:

Class c = int[].class;

方式2:使用对象调用getClass方法获取

int[] arr = new int[4];
Class c = arr.getClass();

获取类类型的Class对象
三种方式
方式1:类型名称直接获取

Class c = Student.class;

方式2:使用Class类中的静态方法forName获取

Class c = Class.forName("全限定名");

方式3:使用对象调用getClass方法获取

Student stu = new Student();
Class c3 = stu.getClass();

3、获取类中信息的方法

3.1 获取类的基本信息

方法名功能补充
getName()获取类的全限定名
getSimpleName()获取类的简单名
getPackage()获取所属的包获取包名:getPackage().getName()
getModifiers()返回此类或接口的修饰符的整数编码常和Modifier类中的toString()方法搭配使用,可以获取修饰符名称
getSuperclass()获取父类型搭配getName使用获取父类类名
getInterfaces()返回的是一个数组。返回由该对象表示的类或接口实现的接口搭配Arrays工具类中的toString方法使用
isAssignableFrom()判断类对象表示的类或接口是否与由指定的Class 类表示的类或接口相同

例如:
以下均以Student类为例进行操作

package blog_1.reflect_0;

interface Action{
	void run();
}

interface Mark{
	void star();
}
public class Student implements Action,Mark{
	private String name; //私有 
	int age; //普通
	public static int num; //静态
	
	public Student()	{}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	//定义普通方法
	public String sayHello(String name) {
		return "hello!" + name;
	}

	//重写接口中的方法
	@Override
	public void star() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

package blog_1.reflect_0;

import java.lang.reflect.Modifier;
import java.util.Arrays;

interface Action{
	void run();
}

interface Mark{
	void star();
}
public class Student implements Action,Mark{
	private String name; //私有 
	int age; //普通
	public static int num; //静态
	
	public Student()	{}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	//定义普通方法
	public String sayHello(String name) {
		return "hello!" + name;
	}

	//重写接口中的方法
	@Override
	public void star() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

@SuppressWarnings("all")
class Demo01{
	public static void main(String[] args) throws Exception{
		//这里通过创建学生对象调用getClass()方法获取Class对象
		Student stu = new Student();
		Class c = stu.getClass();
		
		//获取类的全限定名
		System.out.println(c.getName());
		//获取类的简单类名
		System.out.println(c.getSimpleName());
		//获取类所属包的名字
		System.out.println(c.getPackage().getName());
		//获取类的修饰符
		System.out.println(c.getModifiers()); //这里获取的是编码
		System.out.println(Modifier.toString(c.getModifiers())); //间接获取修饰符名
		//获取类的父类型的名字
		System.out.println(c.getSuperclass().getName());
		//获取类实现的所有接口
		System.out.println(Arrays.toString(c.getInterfaces()));
		
		//判断对象所属类型是不是c的父类型
		Class c1 = Object.class;
		Class c2 = Action.class;
		Class c3 = Mark.class;
		Class c4 = String.class;
		
		System.out.println(c1.isAssignableFrom(c)); //判断c1是不是c代表类型的父类型
		System.out.println(c2.isAssignableFrom(c));
		System.out.println(c3.isAssignableFrom(c));
		System.out.println(c4.isAssignableFrom(c));
		
	}
}

结果:
blog_1.reflect_0.Student
Student
blog_1.reflect_0
1
public
java.lang.Object
[interface blog_1.reflect_0.Action, interface blog_1.reflect_0.Mark]
true
true
true
false

3.2 获取类中声明的属性

java中将属性类型都打包到了java.lang.reflect.Field这个包中。

获取类中public修饰的属性,包括继承过来的public属性

方法功能
Field[] getFields()返回一个数组,获取所有权限为public的属性
Field getField(String name)返回一个Field对象,获取权限为public的指定对象

获取类中声明的属性(含私有的)但是不能获取从父类中继承的属性

方法功能
Filed[] getDeclaredFields()返回Class对表示的所有实体的成员变量,但不包括继承过来的属性
Field getDeclaredField(String name)返回Class对象所表示的类或接口的指定已声明成员变量

例如:

public static void main(String[] args) {
		Class c = Student.class;
		
		//获取类中所有声明的属性,不包括从父类继承过来的
		Field[] fields = c.getDeclaredFields();
		
		for(Field f : fields) {
			System.out.println("属性的修饰符:" + Modifier.toString(c.getModifiers()));
			System.out.println("属性的类型:" + f.getType().getName());
			System.out.println("属性的名称:" + f.getName());
			System.out.println("-----------------");
		}
	}

结果:
属性的修饰符:public
属性的类型:java.lang.String
属性的名称:name
--------------------
属性的修饰符:public
属性的类型:int
属性的名称:age
-----------------
属性的修饰符:public
属性的类型:int
属性的名称:num
-----------------

3.3 获取类中声明的方法

获取当前类中的public方法,包含从父类中继承的public方法

方法名功能
Method[] getMethods()返回一个数组,获取所有权限为public的方法
Method getMethod(String name,Class<?>…parameterTypes)返回method对象,获得权限为public的指定方法

获取当前类中声明的方法(包含私有的),但不能获取父类中继承过来的方法

方法名功能
method[] getDeclaredMethods()返回Method类型数组,返回所有方法,不包括从父类继承过来的
Method getDeclaredMethod(String name,Class<?>…parameterTypes)返会Method对象,返回指定公共成员方法,name是指定方法名称,parameterTypes是指定方法参数类型

其他一些相关方法

方法名功能
getReturnType()获取方法返回类型
getParameterTypeCount()获取方法中参数个数
getExceptionTypes()获取方法抛出异常类型
getParameterTypes()获取参数列表

例如:

	public static void main(String[] args) {
		Student stu = new Student();
		Class c = stu.getClass();
		
		Method[] methods = c.getDeclaredMethods();
		for(Method m : methods) {
			//获取方法的修饰符
			System.out.println(Modifier.toString(m.getModifiers()));
			//获取方法的返回类型
			System.out.println(m.getReturnType().getSimpleName());
			//获取方法的名字
			System.out.println(m.getName());
			System.out.println("方法参数个数:" + m.getParameterCount());
			//获取方法的参数列表
			Class<?>[] paramArr = m.getParameterTypes();
			//输出方法的参数列表
			System.out.println("\t" + Arrays.toString(paramArr));
			
			//获取方法所抛出的异常类型
			Class<?>[] exceptionArr = m.getExceptionTypes();
			System.out.println("方法抛出异常个数" + exceptionArr.length);
			
			//输出方法所抛出的异常列表
			System.out.println("\t" + Arrays.toString(exceptionArr));
			System.out.println("----------------------------");
		}
	}

public
void
run
方法参数个数:0
[]
方法抛出异常个数0
[]
----------------------------
public
String
getName
方法参数个数:0
[]
方法抛出异常个数0
[]
----------------------------
public
void
setName
方法参数个数:1
[class java.lang.String]
方法抛出异常个数0
[]
----------------------------
public
void
star
方法参数个数:0
[]
方法抛出异常个数0
[]
----------------------------
public
String
sayHello
方法参数个数:1
[class java.lang.String]
方法抛出异常个数0
[]
----------------------------

java.lang.reflect.Method表示类中的方法

3.4 获取类中声明的构造器

获取当前类中的public构造器

方法名功能
public Constructor<?>[] getConstructors()返回一个数组,数组中是Constructor对象
public Constructor getConstructor(Class<?>…parameterTypes)返回一个指定的构造器对象,class是类名,parameterTypes是参数类型

获取当前类汇总所有的构造器,包含私有的

方法名功能
public Constructor<?>[] getDeclaredConstructors()返回所有 构造器对象
public Constructor getDeclaredConstructors(Class<?> …parameterTypes)返回指定的构造器对象
public static void main(String[] args) {
		Student stu = new Student();
		Class c= stu.getClass();
		
		//获取类中所有的public构造器
		Constructor[] constructors = c.getConstructors();
		for(Constructor constructor : constructors) {
			//构造器的修饰符
			System.out.println(Modifier.toString(constructor.getModifiers()));
			//构造器的名字
			System.out.println(constructor.getName());
			
			//构造器的参数列表
			Class[] paramList = constructor.getParameterTypes();
			System.out.println(java.util.Arrays.toString(paramList));
			
			//构造器的抛出异常
			Class[] exceptionList = constructor.getExceptionTypes();
			System.out.println(java.util.Arrays.toString(exceptionList));
			
			System.out.println("------------------------");
		}
	}

结果:
public
blog_1.reflect_0.Student
[]
[]
------------------------
public
blog_1.reflect_0.Student
[class java.lang.String, int]
[]
------------------------

4、反射访问和赋值属性

访问类中属性
1、非私有非静态属性
set(对象,属性值 ) get(对象)

2、非静态私有属性
先使用setAccessible(true)方法获取访问权限 再使用set(对象,属性值)赋值,通过 get(对象)方法获取

3、静态属性 set(null,属性值) get(null);

public static void main(String[] args) throws Exception {
		Student stu = new Student();
		Class c = stu.getClass();
		
		//获取类中名字叫name的私有属性
		Field f1 = c.getDeclaredField("name");
		//设置私有属性可以被访问,否则会报错
		f1.setAccessible(true);
		
		
		//使用反射的方式给指定对象的name属性赋值为tom
		f1.set(stu, "tom");
		//使用反射的方式获取这个属性的值
		System.out.println(f1.get(stu));
		
		System.out.println("-----------------");
		
		//获取类中名字叫age的属性
		Field f2 = c.getDeclaredField("age");
		f2.set(stu, 20);
		System.out.println(f2.get(stu));
		System.out.println("-----------------");
		
		Field f3 = c.getDeclaredField("num");
		//用反射的方式,给静态属性num赋值,不需要对象
		f3.set(null, 99);
		System.out.println(f3.get(null));
		
	}

结果:
tom
-----------------
20
-----------------
99

5、反射调用方法

反射调用方法的方法:
public Object invoke(Object obj,Object…args)

obj是指要调用方法的对象,静态方法就传null
args表示要调用的方法的参数列表

访问类中方法
1、非静态方法 invoke (obj,params.class)
2、静态方法 invoke(null,params.class)
3、静态无参 invoke(null,null)

public static void main(String[] args) throws Exception{
		Student stu = new Student();
		Class c = stu.getClass();
		
		//获取类中的toString方法,没有参数,这是从父类中继承的方法
		Method m1 = c.getMethod("toString", null); //toString是要获取的方法的名字,后面一个指定是参数
		//利用反射的方式调用stu对象中的这个方法,没有参数,并接收执行结果
		Object result = m1.invoke(stu, null); //括号内前一个参数是对象名,后一个是参数名
		
		//输出执行结果
		System.out.println(result);
		
		System.out.println("-------------");
		
		//获取类中的sayHello方法,需要一个String类型的参数
		Method m2 = c.getMethod("sayHello", String.class);
		
		//通过反射的方式调用stu对象中的而这个方法,参数是“tom”,并接收执行结果
		result = m2.invoke(stu, "tom");
		
		System.out.println(result);
	}

6、反射创建对象

反射调用类中无参构造器创建对象

public static void main(String[] args) throws Exception{
	Class c = Student.class;
	//这里会默认调用无参构造器来创建对象
	Object obj = c.newInstance();
	System.out.println(obj);
}

反射调用类中有参构造器创建对象

public static void main(String[] args) throws Exception{
	Class c = Student.class;
	//获取类中的带参构造器
	Constructor constructor = c.getConstructor(String.class, int.class);
	//调用有参构造器来创建对象,传入对应的参数值
	Object obj = constructor.newInstance("ton",20);
	System.out.println(obj);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值