反射(中)——反射调用普通方法、类中属性

(3)反射调用普通方法

Class类中有如 下两种取得类中普通方法的函数:

A. 取得所有的普通方法:

public Method[] getMethods()获得所有的public修饰的方法(包含父列的方法也包含Object类)

public Method[] getDeclaredMethods()获得所有成员方法,包括私有的但不包括继承的。

B. 取得指定参数的普通方法:

public Method getMethod(String name,Class<?>... parameterTypes)

     获得指定参数的权限为public的普通方法,

public Method getDeclaredMethod(String name,Class<?>... parameterTypes)

  获得指定参数的成员方法,权限任意,且只能是本类中的方法。

C. 调用方法:

Method->public Object invoke(Object obj,Object……args):

    obj:要调用的方法对象;args:调用方法时所传递的实参。

//反射调用普通方法
class Person1{
	public void demon1() {}
	protected void demon2() {}
	private void demon3(String str) {}
}
class Person extends Person1{
	private String name;
    int age;
    //无参构造方法
    public Person() {}
    public void print1() {
    	System.out.println("我是公有的普通方法1");
    }
    public void print2(int age) {
    	System.out.println("我是带有参数的公有的普通方法2"+age);
    }
    protected void print3() {
    	System.out.println("我是受保护、无参的普通方法3");
    }
    private String print4(String name) {
    	System.out.println("我是带有参数的私有的普通方法4");
		return name;
    }
    void print() {
    	System.out.println("我是默认的普通方法5");
    }
}
public class Test1{
	public static void main(String[] args) throws ClassNotFoundException {
		Class<?> class1 = Class.forName("reflect.Person");
		System.out.println("*************获得访问权限为public的所有普通方法(包括父类、Object类)*********");
		//获取所有访问权限为public的普通方法(包括父列和Object类)
		Method[]  methods = class1.getMethods();
		 for (Method method : methods) {
			System.out.println(method);
		}
		System.out.println("***************获得任意访问权限的所有普通方法(仅本类)**************");
		//获取本类中任意访问权限的所有普通方法
		Method[] methods2 = class1.getDeclaredMethods();
		for (Method method : methods2) {
			System.out.println(method);
		}
		System.out.println("***************获得public访问权限的普通方法(包括父类、Object类)**************");
		try {
			//获取访问权限为public的指定方法(包含父类和Object类)
			Method method = class1.getMethod("print2", int.class);
			System.out.println(method);
		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
		System.out.println("***************获得任意访问权限的普通方法(仅本类)**************");
		try {
			//获取本类中任意访问权限的指定方法
			Method method1 = class1.getDeclaredMethod("print4", String.class);
			System.out.println(method1);
			
			//实例化对象
			Object obj = class1.getConstructor().newInstance();
			//解除私有限定
			method1.setAccessible(true);  
			//调用方法,需要两个参数,一个是要调用的对象(获取有反射),一个是实参
			System.out.println("******************方法的调用***********************");
	        Object result = method1.invoke(obj,"lemon");
	        System.out.println(result);
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
			e.printStackTrace();
		}

  

(4)反射调用类中属性

在之前已经成功的实现了类的构造调用、方法调用,除了这两种模式之外还有类中属性调用。

前提:类中的所有属性一定在类对象实例化之后才会进行空间分配,所以此时如果要想调用类的属性,必须保证有实例化对象。通过反射的newInstance()可以直接取得实例化对象(Object类型)

Class类中提供有两组取得属性的方法:

A.  public Field[] getFields():获取类中访问权限为public的所有属性。

public Field[] getDeclaredFields():获取所有属性,包括:私有、受保护默认、公有; 

B. public Field getField(String fieldName):获取指定权限为public的共有指定      属性

       public Field getDeclaredField(String fieldName):获取任意权限的指定属性

//反射调用类中属性
class Person{
	public String name;
	int age;
	private String work;
}
class Student extends Person{
	private String classes;
	protected char gender;
	public long ID;
}
public class Test1{
	public static void main(String[] args) throws Exception {
		Class<?> class1 = Class.forName("reflect.Student");
		//获取访问权限为public的所有属性(包含父类)
		Field[] fields = class1.getFields();
		System.out.println("***************获得权限为public的所有属性(包含父类)************************");
		for (Field field : fields) {
			System.out.println(field);
		}
		//获取访问权限任意的所有属性
		Field[] fields2 = class1.getDeclaredFields();
		System.out.println("***************获得本类中权限任意的所有属性************************");
		for (Field field : fields2) {
			System.out.println(field);
		}
			//获取访问权限为public的指定属性
			Field field = class1.getField("name");
			System.out.println("***************获得权限位public的的指定属性(包含父类)************************");
			System.out.println(field);
			//获取访问权限任意的本类中的指定属性
			Field field2  = class1.getDeclaredField("classes");
			System.out.println("***************获得本类中权限任意的指定属性************************");
			System.out.println(field2);
	}
}

C. 通过反射操作属性

通过反射机制我们可以利用setget来动态的操作属性的值,若需要对private私有属性进行操纵时,则要用到AccessibleObject类中提供有一个方法:

public void setAccessible(boolean flag):动态设置封装性只此一次(指的是在当前的JVM中)。

Field类中还有一个重要方法:

public Class<?> getType():可以取得属性类型

package reflect;
import java.io.ObjectInputStream.GetField;
import java.lang.reflect.Field;
class Person1{
	private String name;
}
public class Test2 {
	public static void main(String[] args) throws Exception {
		Class<?> class1 = Class.forName("reflect.Person1");
		//实例化本类对象
		Object object = class1.newInstance();
		System.out.println(object);
		//操作name属性
		Field field = class1.getDeclaredField("name");
		//取消封装
		field.setAccessible(true);
		//设置属性 相当于    对象.name = "lemon"
		field.set(object, "lemon");
		//取得属性
		System.out.println(field.get(object));
		//获取属性的类型(返回值:包名.类名)
		System.out.println(field.getType());
		//获取属性的类型(只返回类名)
		System.out.println(field.getType().getSimpleName());
	 }
}
                     

猜你喜欢

转载自blog.csdn.net/qq_40409115/article/details/80259092