Java-反射

Posted 似水之心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-反射相关的知识,希望对你有一定的参考价值。

本文是参考文末的文章自己动手写的笔记

反射

反射就是把java类中的各种成分映射成一个个的Java对象。

获取Class对象的三种方式

  1. Object ——> getClass();
  2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性。
  3. 通过Class类的静态方法:forName(String className)最常用的
    举例
package reflect;

//没什么用,只是用来继承的;
public class SuperDrink {
	public String a;
	protected String b;
	String c;
	private String d;
	
	
	public SuperDrink() {
		super();
		System.out.println("调用SuperDrink的无参构造函数...");
	}
	public String getA() {
		return a;
	}
	public void setA(String a) {
		this.a = a;
	}
	public String getB() {
		return b;
	}
	public void setB(String b) {
		this.b = b;
	}
	public String getC() {
		return c;
	}
	public void setC(String c) {
		this.c = c;
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
	
	public void show1() {
		System.out.println("调用SuperDrink的公用方法show1...");
	}

	protected void show2() {
		System.out.println("调用SuperDrink的受保护的方法show2...");
	}

	void show3() {
		System.out.println("调用SuperDrink的方法show3...");
	}

	private void show4() {
	
		System.out.println("调用SuperDrink的私有方法show4");
	}
	
}


package reflect;

public class Drink extends SuperDrink{
	private double price;
	String name;
	protected int capacity;
	public String desc;

	public Drink(double price) {
		// super();
		this.price = price;
		System.out.println("调用了Drink的公有的构造方法...");
	}

	protected Drink(String name, double price) {
		this.name = name;
		this.price = price;
		System.out.println("调用了Drink的受保护的构造方法...");
	}

	Drink(int capacity) {
		this.capacity = capacity;
		System.out.println("调用了Drink的默认权限的构造方法...");
	}

	private Drink(String name) {
		this.name = name;
		System.out.println("调用了Drink的私有的构造方法...");
	}

	public Drink() {
		super();
		System.out.println("调用了Drink的无参数构造方法...");
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public String getName() {
		return name;
	}

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

	public int getCapacity() {
		return capacity;
	}

	public void setCapacity(int capacity) {
		this.capacity = capacity;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public void show1() {
		System.out.println("调用Drink的公用方法show1...");
	}

	protected void show2() {
		System.out.println("调用Drink的受保护的方法show2...");
	}

	void show3() {
		System.out.println("调用Drink的方法show3...");
	}

	private void show4(String desc) {
		this.desc = desc;
		System.out.println("调用Drink的私有方法show4");
	}

}

package reflect;

public class DrinkTest {
	 public static void main(String[] args) {
		Drink drink = new Drink(12);
		Drink drink1 = new Drink(13);
		
		//第一种:通过对象的getClass()方法
		System.out.println(drink.getClass().getName());
		System.out.println(drink.getClass()==drink1.getClass());
		
		//第二种:通过class属性;
		System.out.println(Drink.class==drink.getClass());
		
		//第三种:通过Class类的静态方法forName();		
		try {
			//需要带上包名;
			System.out.println(Class.forName("reflect.Drink")==drink.getClass());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
}


运行结果

在运行期间一个类只有一个Class对象产生

通过反射获取构造函数

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class DrinkConstructorTest {
	public static void main(String[] args) throws Exception {
		Class drinkClass = Class.forName("reflect.Drink");
		
		System.out.println("******************************返回所有的公有构造函数**************************");
		/*
		 * Returns an array containing {@code Constructor} objects reflecting all the
		 * public constructors of the class represented by this {@code Class} object. An
		 * array of length 0 is returned if the class has no public constructors, or if
		 * the class is an array class, or if the class reflects a primitive type or
		 * void.
		 * 第一种:返回所有的公有构造函数,但如果没有公有的构造函数或者是数组类型或者为基本类型(例如;int等)或者void类型,就返回长度为0 的数组。
		 */
		Constructor[] constructors = drinkClass.getConstructors(); //显然在这个例子中只有两个公有的构造函数
		for(Constructor obj:constructors) {
			System.out.println(obj);
		}
		
		System.out.println("******************************返回特定某个公有构造函数**************************");
		//第二种:通过传入参数获取特定公有构造函数;
		Constructor constructor1 = drinkClass.getConstructor();
		Constructor constructor2 = drinkClass.getConstructor(double.class);
		System.out.println(constructor1);
		System.out.println(constructor2);
		
		
		System.out.println("******************************返回所有的构造函数(包括公有,受保护的,默认的,私有的)**************************");
		 /**
	     * Returns an array of {@code Constructor} objects reflecting all the
	     * constructors declared by the class represented by this
	     * {@code Class} object. These are public, protected, default
	     * (package) access, and private constructors.  The elements in the array
	     * returned are not sorted and are not in any particular order.  If the
	     * class has a default constructor, it is included in the returned array.
	     * This method returns an array of length 0 if this {@code Class}
	     * object represents an interface, a primitive type, an array class, or
	     * void.
	     *  第三种:返回所有的公有构造函数,但如果没有公有的构造函数或者是接口或者数组类型或者为基本类型(例如;int等)或者void类型,就返回长度为0 的数组。
	     */
		Constructor[] constructor3 = drinkClass.getDeclaredConstructors();
		for(Constructor obj:constructor3) {
			System.out.println(obj);
		}
		
		System.out.println("******************************返回特定某个构造函数(包括公有,受保护的,默认的,私有的)**************************");
		Constructor constructor4 = drinkClass.getDeclaredConstructor();
		Constructor constructor5 = drinkClass.getDeclaredConstructor(String.class);
		Constructor constructor6 = drinkClass.getDeclaredConstructor(int.class);
		Constructor constructor7 = drinkClass.getDeclaredConstructor(String.class,double.class);
		Constructor constructor8 = drinkClass.getDeclaredConstructor(double.class);
		System.out.println(constructor4);
		System.out.println(constructor5);
		System.out.println(constructor6);
		System.out.println(constructor7);
		System.out.println(constructor8);
		
		System.out.println("******************************通过构造函数获取实例对象**************************");
		Drink drinkInstance1 = (Drink) constructor1.newInstance();
		Drink drinkInstance2 = (Drink) constructor2.newInstance(10);
		constructor5.setAccessible(true); //强行修改访问权限;
		Drink drinkInstance3 = (Drink) constructor5.newInstance("雪碧"); //私有的构造函数;	
		System.out.println(drinkInstance2.getPrice());
		System.out.println(drinkInstance3.getName());
		
	}
}



注意获取某个特定构造函数的时候参数传递
运行结果

获取所有的成员变量

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class DrinkVariableTest {
	public static void main(String[] args) throws Exception {
		Class drinkClass = Class.forName("reflect.Drink");
		System.out.println("************************所有公有的成员变量(包括继承的)*******************");
		/*
		 * Returns an array containing {@code Field} objects reflecting all the
		 * accessible public fields of the class or interface represented by this {@code
		 * Class} object.
		 */
		//获取所有的公有成员变量;
		Field[] fields = drinkClass.getFields();
		for(Field obj:fields) {
			System.out.println(obj);//这里只有des是public的;
		}
		
		System.out.println("************************单个公有的成员变量*******************");
		Field field1 = drinkClass.getField("desc"); //成员变量的名称;
		Field field4 = drinkClass.getField("a"); //成员变量的名称;
		System.out.println(field1);
		System.out.println(field4);
		
		System.out.println("************************所有的成员变量(包括公有、受保护的、默认的、私有的,但除去继承的)*******************");
		/**
	     * Returns an array of {@code Field} objects reflecting all the fields
	     * declared by the class or interface represented by this
	     * {@code Class} object. This includes public, protected, default
	     * (package) access, and private fields, but excludes inherited fields.
	     *
	     */
		Field[] fields1 = drinkClass.getDeclaredFields();
		for(Field obj:fields1) {
			System.out.println(obj);
		}
		
		System.out.println("************************特定的成员变量(包括公有、受保护的、默认的、私有的,但除去继承的)*******************");
		Field field2 = drinkClass.getDeclaredField("price"); //price是私有属性;
		System.out.println(field2); 
		field2.setAccessible(true);//解除私有不可访问;
		
		System.out.println("************************使用*******************");
		Field field3 = drinkClass.getDeclaredField("name");
		Drink drink = (Drink) drinkClass.getDeclaredConstructor(int.class).newInstance(450); 
		field2.set(drink, 10); //已经解除访问 权限;
		field3.set(drink,"雪碧"); 
		System.out.println(drink.getPrice()); 
		System.out.println(drink.getName());
		
		
		
		
		
		
	}

}


运行结果

获取成员方法

package reflect;

import java.lang.reflect.Method;

public class DrinkMethodTest {
	public static void main(String[] args) throws Exception{
		Class drinkClass = Class.forName("reflect.Drink");
		
		System.out.println("**************第一种:所有的公有方法(包括继承的父类的和父接口的)");
		 /**
	     * Returns an array containing {@code Method} objects reflecting all the
	     * public methods of the class or interface represented by this {@code
	     * Class} object, including those declared by the class or interface and
	     * those inherited from superclasses and superinterfaces.
	     */
		Method[] methods = drinkClass.getMethods();
		for(Method obj:methods) {
			System.out.println(obj);
		}
		
		System.out.println("**************第二种:特定公有方法(可以是继承的父类的和父接口的)");
		Method method1 = drinkClass.getMethod("show1"); //需要填写方法名以及参数的类型,这里show1没有参数,所以省略;
		Method method2 = drinkClass.getMethod("notify"); //需要填写方法名以及参数的类型,这里show1没有参数,所以省略;
		System.out.println(method1);
		System.out.println(method2);
		
		System.out.println("**************第三种:所有方法(公有的、受保护的、私有的、默认的,但不包括继承的父类的和父接口的)");
		 /**
	     *
	     * Returns an array containing {@code Method} objects reflecting all the
	     * declared methods of the class or interface represented by this {@code
	     * Class} object, including public, protected, default (package)
	     * access, and private methods, but excluding inherited methods.
	     */
		Method[] methods1 = drinkClass.getDeclaredMethods();
		for(Method obj:methods1) {
			System.out.println(obj);
		}
		
		System.out.println("**************第四种:特定方法(公有的、受保护的、私有的、默认的,但不包括继承的父类的和父接口的)");
		Method method3 = drinkClass.getDeclaredMethod("show2");
		System.out.println(method3);
		Method method4 = drinkClass.getDeclaredMethod("show4",String.class);
		System.out.println(method4);
		method4.setAccessible(true);//暴力解除访问权限;
		
		
		System.out.println("**************使用******************");
		//注意这里需要使用getDeclaredConstructor()因为参数所对应的构造函数是默认包访问权限的;
		Drink drink = (Drink) (Drink) drinkClass.getDeclaredConstructor(int.class).newInstance(450); ;
		method3.invoke(drink);//填入obj和参数;
		method4.invoke(drink,"饮品的一种");
	}
}


运行结果

其它

反射main方法、通过反射运行配置文件内容、通过反射越过泛型检查。

总结

1、区分getDeclaredXX()和getXX()方法,前者是指该类所有的(包括公有、私有、受保护和默认访问权限),后者只包括公有的。同时,对于变量和方法而言,前者不包括继承的,而后者需要包继承父类的(所有的祖先);
2、可以通过不管是构造函数、变量还是方法可以使用setAccessible()将私有权限设置为外界可访问的,但这样做其实不太好。

参考

https://blog.csdn.net/sinat_38259539/article/details/71799078

以上是关于Java-反射的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

反射机制入门

使用反射在外部JAR / CLASS上调用包含Hibernate事务的方法(Java EE)

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

OpenGL片段着色器不照亮场景