文档章节

Java 反射

tsmyk0715
 tsmyk0715
发布于 2017/06/05 12:01
字数 2431
阅读 17
收藏 0
点赞 0
评论 0

Java 反射

1. 获取 Class 的三种方法:

public class Clazz01 {

	public Class<?> method01(){
		Class<?> clazz = Clazz01.class;
		return clazz;
	}
	
	//常用
	public Class<?> method02(){
		try {
			Class<?> clazz = Class.forName("reflect.Clazz01");
			return clazz;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Class<?> method03(){
		Clazz01 clazz01 = new Clazz01();
		Class<?> clazz = clazz01.getClass();
		return clazz;
	}
	
	public static void main(String[] args) {
		Clazz01 c = new Clazz01();
		Class<?> clazz1 = c.method01();
		Class<?> clazz2 = c.method02();
		Class<?> clazz3 = c.method03();
		System.out.println(clazz1);//class reflect.Clazz01
		System.out.println(clazz2);//class reflect.Clazz01
		System.out.println(clazz3);//class reflect.Clazz01
		System.out.println(clazz1.equals(clazz2));//true
		
		System.out.println(clazz1.getName());//reflect.Clazz01
		System.out.println(clazz1.getSimpleName());//Clazz01
	}
}

2. Class 实例化对象

参考的类:

class Person {

	private String name;

	private int age;

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

	public Person(String name) {
		this.name = name;
	}

	public Person() {
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}
	
class Person2 {

	private String name;

	private int age;

	private Person2(String name, int age) {
		this.name = name;
		this.age = age;
	}

	protected Person2(String name) {
		this.name = name;
	}

	public Person2() {
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

首先获取 **Class**对象:

Class<?> clazz = Class.forName("reflect.Person");

这种方式通过无参构造实例化对象,此时类中必须有一个无参的构造器,否则报错。

通过 **newInstance()**来实例化对象,之后调用相应的方法设置属性值:

Person person = (Person) clazz.newInstance();
person.setName("zhangsan");
person.setAge(20);
System.out.println(person);
// Person [name=zhangsan, age=20]

<br> #####获取构造函数的四种方式:

这两种方式只能获取得到 public 修饰的构造函数:

Constructor<?>[] getConstructors():获取所有的构造函数

Constructor<T> getConstructor(Class<?>... parameterTypes):通过对应的参数看获取对应的构造函数

<br> 这两种方式可以获取到所有的构造函数:`public`, `protected`, `private`,`default`, 常用

Constructor<?>[] getDeclaredConstructors()

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

<br> #####1. **`getConstructors()`** : 获取所有的 public 修饰的构造函数:

Constructor<?> cons[] = clazz.getConstructors();
for (int i = 0; i < cons.length; i++) {
	System.out.println(cons[i].toString());
}

结果:

public reflect.Person() 
public reflect.Person(java.lang.String) 
public reflect.Person(java.lang.String, int)

newInstance()的重载:

Person p1 = (Person) cons[0].newInstance();
System.out.println(p1);// Person [name=null, age=0]

Person p2 = (Person) cons[1].newInstance("lisi");
System.out.println(p2);// Person [name=lisi, age=0]

Person p3 = (Person) cons[2].newInstance("lisi", 20);
System.out.println(p3);// Person [name=lisi, age=20]

<br>

2. Constructor<T> getConstructor(Class<?>... parameterTypes): 根据参数来获取 public 修饰的构造函数
Constructor<?> con = clazz.getConstructor(String.class);
Person p4 = (Person) con.newInstance("lisi");
System.out.println(p4);//Person [name=lisi, age=0]

<br> ##### 3. `getDeclaredConstructors()` : 获取所有的类型的构造函数: `public`, `protected`, `private`, `default`:

Class<?> clazz2 = Class.forName("reflect.Person2");
Constructor<?>[] cons2 = clazz2.getDeclaredConstructors();
for (int i = 0; i < cons2.length; i++) {
	System.out.println(cons2[i].toString());
}

结果:

public reflect.Person2() 
protected reflect.Person2(java.lang.String)  
private reflect.Person2(java.lang.String,int)

<br> #####4. `Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)` : 根据参数获取 `private `的构造函数

	Constructor<?> c = clazz2.getDeclaredConstructor(String.class,int.class);
	System.out.println(c);
	//private reflect.Person2(java.lang.String,int)
	c.setAccessible(true);//为 true, 则可以访问所有的方法和字段,包括 private
	
	Person2 p = (Person2) c.newInstance("zhangsan", 20);
	System.out.println(p);//Person [name=zhangsan, age=20]

<br> #### 3. 获取类实现的 接口 和 父类

参考的类:

interface World<A, B> {
	void sayWorld();	
	A getA();	
	B getB();
}

interface A {

}

interface B {

}

abstract class China<T> {
	public static final String name = "lisi";
	public static final int age = 20;
	public abstract void sayChina();
	public abstract void hello(String name);
}

class Person3<T> extends China<T> implements World<A, B>, A, B {

	[@Override](https://my.oschina.net/u/1162528)
	public void sayWorld() {
		System.out.println("say world...");
	}

	[@Override](https://my.oschina.net/u/1162528)
	public void sayChina() {
		System.out.println("say china...");
	}

	[@Override](https://my.oschina.net/u/1162528)
	public void hello(String name) {
		System.out.println("hello : " + name);
	}

	@Override
	public A getA() {
		return null;
	}

	@Override
	public B getB() {
		return null;
	}
}

<br> ##### 获取类所实现的===> 接口

getInterfaces() : 返回本类直接实现的所有接口. 不包含泛型参数信息

Class<?> clazz = Class.forName("reflect.Person3");

.

Class<?>[] interfs = clazz.getInterfaces();
	for (Class<?> interf : interfs) {
		// 获取接口的名字
		System.out.println(interf.getName());// reflect.World
		// 获取接口下的所有方法,包括 prorected, private
		Method[] methods = interf.getDeclaredMethods();
		for (Method method : methods) {
			// 获取方法名
			System.out.println(method.getName());// sayWorld
		}
}

结果:

reflect.World 
sayWorld 
getA 
getB
 
reflect.A 
reflect.B

<br> `getGenericInterfaces()`: 以**`Type`**的形式返回本类直接实现的接口. 这样就包含了泛型参数信息

Type[] types = clazz.getGenericInterfaces();
for (Type type : types) {
	System.out.println(type);
}

结果:

reflect.World<reflect.A, reflect.B> 
interface reflect.A 
interface reflect.B

<br> ##### 获取本类的===>父类

getSuperclass() : 不包含泛型信息

 Class<?> supClazzes = clazz.getSuperclass();
String className = supClazzes.getName();
System.out.println(className);//reflect.China

getGenericSuperclass() : 包含泛型信息

Type type =clazz.getGenericSuperclass();
System.out.println(type);//reflect.China<T>

<br> ####4. 获取所有的方法

参考的类:

abstract class China2 {
	public static final String name = "lisi";		
	public static final int age = 20;	
	protected abstract void sayChina();	
	abstract void hello(String name);
}

class Person4 extends China2{

	private String sex;

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	protected void sayChina() {
		System.out.println("say china...");
	}

	@Override
	void hello(String name) {
		System.out.println("hello : " + name);
	}

	private Person4(String sex) {
		super();
		this.sex = sex;
	}

	public Person4() {
		super();
	}
	
}

首先获取 Class 对象:

Class<?> clazz = Class.forName("reflect.Person4");

通过反射来获取一个类的方法:

  1. getMethods(): 获取本类中的所有 public的方法,包括所实现的接口和父类中的方法
  2. getMethod(String name, Class<?>... parameterTypes) : 根据方法名和参数来获取对应的public方法, 可以获取实现的 接口 和 父类 中的方法
  3. getDeclaredMethods() : 获取本类中所有的方法,包括 protected, privatedefault, 不包含接口和父类
  4. getDeclaredMethods(String name, Class<?>... parameterTypes) : 根据方法名和参数来获取对应的方法,包括protected, private, default,但是不包含继承来的方法

getMethods(): 只能获取 public 修饰的方法,可以获取实现的 接口 和 父类 中的方法

	Method[] methods = clazz.getMethods();
	for (Method method : methods) {
		
		// 获取访问修饰符
		int modifier = method.getModifiers();
		System.out.print(Modifier.toString(modifier) + " ");
		
		// 获取返回值类型
		Class<?> returnType = method.getReturnType();
		String returnTypeName = returnType.getName();
		System.out.print(returnTypeName + " ");
		
		// 获取方法名
		String methodName = method.getName();
		System.out.print(methodName);
			
		System.out.print("(");
		
		// 获取参数类型
		Class<?>[] paramTypes = method.getParameterTypes();
		// 获取参数
		Parameter[] params = method.getParameters();
		for(int i = 0; i < paramTypes.length; i++){
			System.out.print(params[i]);// 参数已经包含类型信息了:java.lang.String arg0
			if(i < paramTypes.length - 1){
				System.out.print(", ");
			}
		}
		
		// 获取异常类型
		Class<?>[] exceptionTypes = method.getExceptionTypes();
		if(exceptionTypes.length > 0){
			System.out.print(") throws ");
			for (int i = 0; i < exceptionTypes.length; i++) {
				System.out.println(exceptionTypes[i].getName());
				if(i < exceptionTypes.length - 1){
					System.out.print(", ");
				}
			}
		}else{
			System.out.println(")");
		}
		System.out.println();
	}

结果:

public java.lang.String getSex()	 
public void setSex(java.lang.String arg0)	
public final void wait() throws java.lang.InterruptedException	
public final void wait(long arg0, int arg1) throws java.lang.InterruptedException  	
public final native void wait(long arg0) throws java.lang.InterruptedException	

public boolean equals(java.lang.Object arg0)

<br> **`getMethod(String name, Class<?>... parameterTypes)`**根据方法名称可参数来获取对应的 public 方法,可以获取实现的 接口 和 父类 中的方法

Method me = clazz.getMethod("getSex");
System.out.println(me);
//public java.lang.String reflect.Person4.getSex()

<br> **`getDeclaredMethods()`** 获取本类中所有的方法, 包括 protected, private 的方法

Method[] decMethods = clazz.getDeclaredMethods();
for(Method m : decMethods){
	System.out.println(m.getName());
}

结果:

getSex
hello
setSex
sayChina

<br> **`getDeclaredMethods(String name, Class<?>... parameterTypes)` **根据方法名和参数类型获取所有方法,包括 protected, private, defalut

Method m = clazz.getDeclaredMethod("hello", String.class);
System.out.println(m);
//void reflect.Person4.hello(java.lang.String)

<br> ####5. 获取属性

参考的类:

class FPerson{
	private String name;
	int age;
	protected float weight;
	public boolean isMen;
}

class Person_ extends FPerson{
	private byte photo;
	char pchar;
	protected short hight;
	public double sing;
}

<br> 首先获取**`Class`**对象:

Class<?> clazz = Class.forName("reflect.Person_");

获取属性的四个方法:

  1. getFields(): 获取本类中所有的 public 属性,包括父类中的属性
  2. getField(String name): 根据属性名类获取 Field
  3. getDeclaredFields(): 获取本类中所有的属性,包括 protected, private,default, 不能获取父类的属性
  4. getDeclaredField(String name): 根据参数来获取本类的属性,包括 protected, private,default, 不能获取父类的属性, 不包含父类

**getFields()**获取本类中所有的 public 属性,包括父类中的属性

Field[] fields = clazz.getFields();
for(Field field : fields){
	// 获取修饰符
	int mod = field.getModifiers();
	System.out.print(Modifier.toString(mod) + " ");
	
	// 获取属性的类型
	Class<?> type = field.getType();
	System.out.print(type + " ");
	
	String name = field.getName();
	System.out.println(name);
}

结果:

public double sing
public boolean isMen

getField(String name) : 根据属性名类获取 Field, 若在本类中找不到对应的属性,或者有这个属性,但是修饰符不是 public,(也包括在父类中查找), 则会抛出异常:java.lang.NoSuchFieldException

Field f = clazz.getField("isMen");
System.out.println(f);
//public boolean reflect.FPerson.isMen

**getDeclaredFields()**获取本类中所有的属性,包括 protected, private,default, 不能获取父类的属性

Field[] decFields = clazz.getDeclaredFields();
for(Field field : decFields){
	// 获取修饰符
	int mod = field.getModifiers();
	System.out.print(Modifier.toString(mod) + " ");
	
	// 获取属性的类型
	Class<?> type = field.getType();
	System.out.print(type + " ");
	
	String name = field.getName();
	System.out.println(name);
}

结果:

private byte photo
 char pchar
protected short hight
public double sing

getDeclaredField(String name) : 根据参数来获取本类的属性,包括 protected, private,default, 不能获取父类的属性, 不包含父类

<br> #### 6. Class, Field, Method 的一些方法:

参考的类:

class Person6{

	private String name;
	private int age;
	private boolean isMen;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isMen() {
		return isMen;
	}
	public void setMen(boolean isMen) {
		this.isMen = isMen;
	}
	public Person6(String name, int age, boolean isMen) {
		super();
		this.name = name;
		this.age = age;
		this.isMen = isMen;
	}
	public Person6() {
		super();
	}
	
	public String teseMethod(String name, int age, boolean men) throws Exception{
		return "test Method'method";
	}
}

<br> 首先获取 `Class`对象:

Class<?> clazz = Class.forName("reflect.Person6");

#####Class的方法:

toGenericString(): 返回CLass, Constructor,Method,Field的详细信息

返回 Class 的详细信息:

String str = clazz.toGenericString();
System.out.println(str);//class reflect.Person6

返回构造方法的详细信息

Constructor<?> cons = clazz.getDeclaredConstructor(String.class, int.class, boolean.class);
System.out.println(cons.toGenericString());
// public reflect.Person6(java.lang.String,int,boolean)

getPackage()获取包

Package pack = clazz.getPackage();
System.out.println(pack);// package reflect
System.out.println(pack.getName());// reflect

getCanonicalName(): 返回 Java 中所定义的底层类的规范化名称。

String canonicalName = clazz.getCanonicalName();
System.out.println(canonicalName);//reflect.Person6

getComponentType: 返回表示数组组件类型的 Class

String[] strArr = {"a", "b", "c"};
Class<?> componentType = strArr.getClass().getComponentType();
System.out.println(componentType.getName());// java.lang.String

<br> #####`Field` 的方法:

Field field = clazz.getDeclaredField("name");

setAccessible(): 设置可以访问私有的属性

	field.setAccessible(true);

getGenericType() : 返回Field 对象所表示字段的类型

	Type type = field.getGenericType();
	System.out.println(type.getTypeName());//java.lang.String

getModifiers():以整数形式返回由该字段的修饰符。

int mod = field.getModifiers();
// Modifier 表示类,接口,属性,方法的修饰符的类
String modStr = Modifier.toString(mod);
System.out.println(mod + "==>" + modStr);// 2==>private

<br> ####7. Java 的动态代理

interface Subject{
	String work(String param);
}

class RealSubject implements Subject{
	@Override
	public String work(String param) {
		return param;
	}
}

class MyHandler implements InvocationHandler{

	private Object obj;
	
	public Object bind(Object obj){
		this.obj = obj;
		Object returnObj = Proxy.newProxyInstance(obj.getClass().getClassLoader(),
				obj.getClass().getInterfaces(), this);
		return returnObj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object tmp = method.invoke(obj, args);
		return tmp;
	}
}

测试:

public static void main(String[] args) {
	MyHandler handler = new MyHandler();
	Subject subject = (Subject) handler.bind(new RealSubject());
	String str = subject.work("Java 的动态代理");
	System.out.println(str);
}

结果: Java 的动态代理

8. 使用反射实现工厂模式

// 以后再添加 Animal 的子类,工厂类也不用修改
class AnimalFactory{
	public static Animal getInstance(String className){
		Animal animal = null;
		try {
			animal = (Animal) Class.forName(className).newInstance();
			return animal;
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}

interface Animal{
	void run();
}
class Dog implements Animal{
	@Override
	public void run() {
		System.out.println("dog is running");
	}
}
class Cat implements Animal{
	@Override
	public void run() {
		System.out.println("cat is running");
	}
}

测试:

public static void main(String[] args) {
	Animal dog = AnimalFactory.getInstance("reflect.Dog");
	dog.run();// dog is running
	
	Animal cat = AnimalFactory.getInstance("reflect.Cat");
	cat.run();// cat is running
}

看个实际的例子: 利用反射来把父类的属性复制到子类
输入链接说明

© 著作权归作者所有

共有 人打赏支持
tsmyk0715
粉丝 11
博文 36
码字总数 78650
作品 0
成都
程序员

暂无文章

SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
4
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
1
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
165
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部