Java 反射
Java 反射
tsmyk0715 发表于5个月前
Java 反射
  • 发表于 5个月前
  • 阅读 15
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

摘要: Java 反射

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]

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

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

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

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


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

Constructor<?>[] getDeclaredConstructors()

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


#####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]

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]

##### 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)

#####4. `Constructor 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]

#### 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;
	}
}

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

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

`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

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

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>

####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)

**`getMethod(String name, Class... parameterTypes)`**根据方法名称可参数来获取对应的 public 方法,可以获取实现的 接口 和 父类 中的方法
Method me = clazz.getMethod("getSex");
System.out.println(me);
//public java.lang.String reflect.Person4.getSex()

**`getDeclaredMethods()`** 获取本类中所有的方法, 包括 protected, private 的方法
Method[] decMethods = clazz.getDeclaredMethods();
for(Method m : decMethods){
	System.out.println(m.getName());
}

结果:

getSex
hello
setSex
sayChina

**`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)

####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;
}

首先获取**`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, 不能获取父类的属性, 不包含父类


#### 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";
	}
}

首先获取 `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

#####`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

####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
}
共有 人打赏支持
粉丝 6
博文 48
码字总数 36206
×
tsmyk0715
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: