文档章节

Java 反射

tsmyk0715
 tsmyk0715
发布于 2017/06/05 12:01
字数 2431
阅读 18
收藏 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
粉丝 21
博文 43
码字总数 98538
作品 0
成都
程序员

暂无文章

20180920 rzsz传输文件、用户和用户组相关配置文件与管理

利用rz、sz实现Linux与Windows互传文件 [root@centos01 ~]# yum install -y lrzsz # 安装工具sz test.txt # 弹出对话框,传递到选择的路径下rz # 回车后,会从对话框中选择对应的文件传递...

野雪球
今天
1
0
OSChina 周四乱弹 —— 毒蛇当辣条

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 达尔文:分享花澤香菜/前野智昭/小野大輔/井上喜久子的单曲《ミッション! 健?康?第?イチ》 《ミッション! 健?康?第?イチ》- 花澤香菜/前野智...

小小编辑
今天
7
3
java -jar运行内存设置

java -Xms64m #JVM启动时的初始堆大小 -Xmx128m #最大堆大小 -Xmn64m #年轻代的大小,其余的空间是老年代 -XX:MaxMetaspaceSize=128m # -XX:CompressedClassSpaceSize=6...

李玉长
今天
3
0
Spring | 手把手教你SSM最优雅的整合方式

HEY 本节主要内容为:基于Spring从0到1搭建一个web工程,适合初学者,Java初级开发者。欢迎与我交流。 MODULE 新建一个Maven工程。 不论你是什么工具,选这个就可以了,然后next,直至finis...

冯文议
今天
2
0
RxJS的另外四种实现方式(四)——性能最高的库(续)

接上一篇RxJS的另外四种实现方式(三)——性能最高的库 上一篇文章我展示了这个最高性能库的实现方法。下面我介绍一下这个性能提升的秘密。 首先,为了弄清楚Most库究竟为何如此快,我必须借...

一个灰
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部