JAVA 基础 反射技术


  • 1 Class 对象的三种获取方式
        
package demo1;

public class Test1 {

	public static void main(String[] args) throws Exception {
		//演示对象
		Person p = new Person();
		//获得Class对象的三种方式
		//1 对象.getClass方法获得
		Class c1 = p.getClass();
		//2 类名.Class 静态属性 获得
		Class c2 = Person.class;
		//3 Class.forName()方法获得
		Class c3 = Class.forName("demo1.Person");
		System.out.println("c1:"+c1);
		System.out.println("c2:"+c2);
		System.out.println("c3:"+c3);
	}
}

  •   2  通过反射获取构造方法并使用
package demo1;

import java.lang.reflect.Constructor;

public class Test2 {
	/*
	 * 
	 * 通过反射获取构造方法并使用
	 * 
	 */
	
	public static void main(String[] args) throws Exception {
		//----------获得Class对象----------
		Class c = Class.forName("demo1.Person");
		
		//----------获得所有构造方法----------
		Constructor[] cons =  c.getConstructors();
		for(Constructor con : cons) {
			System.out.println(con);
		}
		/*
		 * 输出
		 * public demo1.Person()
		 * public demo1.Person(java.lang.String,java.lang.String,int,java.lang.String)
		 */
		
		//----------获得共有构造方法----------
		
		//获得空参构造方法
		Constructor con = c.getConstructor();
		System.out.println(con);
		//输出 public demo1.Person()
		
		//获得指定参数构造方法
		//public Constructor<T> getConstructor(Class<?>... parameterTypes) 注意参数室Class对象
		con = c.getConstructor(String.class, String.class, int.class , String.class);
		System.out.println(con);
		//输出 public demo1.Person(java.lang.String,java.lang.String,int,java.lang.String)
		
		//----------获得私有构造方法----------
		
		//获得空参私有构造方法
		cons = c.getDeclaredConstructors();
		for (Constructor con1 : cons) {
			System.out.println(con1);
		}
		//输出 private demo1.Person(java.lang.String)
		
		//获得指定参数构造方法
		con = c.getDeclaredConstructor(String.class);
		System.out.println(con);
		//输出 private demo1.Person(java.lang.String)
		
		
	}
	
}

  • 3 通过反射方式,获取构造方法,创建对象


package demo1;

import java.lang.reflect.Constructor;

public class Test3 {

	/*
	 * 通过反射方式,获取构造方法,创建对象
	 * 获取构造方法,步骤如下:
			1. 获取到Class对象
			2. 获取指定的构造方法
			3. 通过构造方法类Constructor中的方法,创建对象
	 */
	public static void main(String[] args) throws Exception {
		
		//1. 获取到Class对象
		Class c = Class.forName("demo1.Person");
		//2. 获取指定的构造方法
		Constructor<Person> con = c.getConstructor(String.class, String.class, int.class, String.class);
		//3. 通过构造方法类Constructor中的方法,创建对象
		//public T newInstance(Object... initargs)
		//如果Constructor没有写泛形的话,这里应该用Object来接收实例
		Person p = con.newInstance("alex", "男", 33, "coder");
		System.out.println(p);
		//输出 Person [name=alex, sex=男, age=33, title=coder]
		
	}
}

  • 4 通过反射方式,获取私有构造方法,创建对象
package demo1;

import java.lang.reflect.Constructor;

public class Test4 {
	/*
	 * 	通过反射方式,获取私有构造方法,创建对象
	 *  AccessibleObject 类是 Field、Method 和 Constructor 对象的父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。
		对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。常用方法如下:
		public void setAccessible(boolean flag) throws SecurityException 
		参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查。
		
		获取私有构造方法,步骤如下:
		1. 获取到Class对象
		2. 获取指定的构造方法
		3. 暴力访问, 通过setAccessible(boolean flag)方法
		4. 通过构造方法类Constructor中的方法,创建对象
		public T newInstance(Object... initargs)
	 */
	
	public static void main(String[] args) throws Exception {
		
		//1. 获取到Class对象
		Class c = Class.forName("demo1.Person");
		//2. 获取指定的构造方法
		Constructor<Person> con = c.getDeclaredConstructor(String.class);
		System.out.println(con);
		//得到私有构造器 private demo1.Person(java.lang.String)
		//3.暴力访问, 通过setAccessible(boolean flag)方法
		con.setAccessible(true);
		//4. 通过构造方法类Constructor中的方法,创建对象
		//public T newInstance(Object... initargs)
		//如果Constructor没有写泛形的话,这里应该用Object来接收实例
		Person p = con.newInstance("alex");
		System.out.println(p);
		//输出 Person [name=alex, sex=null, age=0, title=null]
		
		
	}
}

  • 5 通过反射获取成员变量并使用
package demo1;

import java.lang.reflect.Field;

public class Test5 {

	/*
	 * 通过反射获取成员变量并使用
	 * 在反射机制中,把类中的成员变量使用类Field表示。可通过Class类中提供的方法获取成员变量:
		返回一个成员变量
		public Field getField(String name) 获取指定的 public修饰的变量
		public Field getDeclaredField(String name) 获取指定的任意变量
		返回多个成员变量
		public Field[] getFields() 获取所有public 修饰的变量
		public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)
	 */
	
	public static void main(String[] args) throws Exception {

		Class c = Class.forName("demo1.Person");
		//--------获得所有共有的成员变量--------
		Field[] fields = c.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		//输出 public java.lang.String demo1.Person.title
		
		//--------获得特定共有的成员变量--------
		Field titleField = c.getField("title");
		System.out.println(titleField);
		//输出 public java.lang.String demo1.Person.title
		
		//--------获得所有私有的成员变量--------
		Field[] fields1 = c.getDeclaredFields();
		for (Field field : fields1) {
			System.out.println(field);
		}
		/*
		 * getDeclaredFields()方法会获得所有的成员变量
		 * 
		 *  private java.lang.String demo1.Person.name
			private java.lang.String demo1.Person.sex
			private int demo1.Person.age
			public java.lang.String demo1.Person.title
		 * 
		 */
		//--------获得特定私有的成员变量--------
		Field nameField = c.getDeclaredField("name");
		Field sexField = c.getDeclaredField("sex");
		Field ageField = c.getDeclaredField("age");
		//用getDeclaredField获得共有成员变量也是可行的
		Field titleField1 = c.getDeclaredField("title");
		System.out.println(nameField);
		System.out.println(sexField);
		System.out.println(ageField);
		System.out.println(titleField1);
		/*
		 * 输出
		 *  private java.lang.String demo1.Person.name
			private java.lang.String demo1.Person.sex
			private int demo1.Person.age
			public java.lang.String demo1.Person.title
		 */
	}
	
}

  • 6 通过反射,创建对象,获取指定的成员变量,进行赋值与获取值操作
package demo1;

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

public class Test6 {

	/*
	 * 通过反射,创建对象,获取指定的成员变量,进行赋值与获取值操作
	 * 获取成员变量,步骤如下:
				1. 获取Class对象
				2. 获取构造方法
				3. 通过构造方法,创建对象
				4. 获取指定的成员变量(私有成员变量,通过setAccessible(boolean flag)方法暴力访问)
				5. 通过方法,给指定对象的指定成员变量赋值或者获取值
				public void set(Object obj, Object value)
				在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
				public Object get(Object obj)
         		返回指定对象obj中,此 Field 对象表示的成员变量的值
	 */
	
	
	public static void main(String[] args) throws Exception {
		//1. 获取Class对象
		Class c = Class.forName("demo1.Person");
		//2. 获取构造方法
		Constructor<Person> con = c.getConstructor(String.class, String.class, int.class, String.class);
		//3. 通过构造方法,创建对象
		Object obj = con.newInstance("alex", "男", 33, "coder");
		//4. 获取指定的成员变量(私有成员变量,通过setAccessible(boolean flag)方法暴力访问)
		Field nameField = c.getDeclaredField("name");
		nameField.setAccessible(true);
		//5. 通过方法,给指定对象的指定成员变量赋值或者获取值
		nameField.set(obj, "alex1");
		System.out.println(obj);
		// 输出 Person [name=alex1, sex=男, age=33, title=coder]
		//获得成员变量值
		System.out.println("成员变量name="+nameField.get(obj));
		
	}
}

  • 7 通过反射获取成员方法并使用
package demo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Test7 {

	/*
	 * 通过反射获取成员方法并使用
	 * 
	 * 	在反射机制中,把类中的成员方法使用类Method表示。可通过Class类中提供的方法获取成员方法:
		返回获取一个方法:
		public Method getMethod(String name, Class<?>... parameterTypes)
		 			获取public 修饰的方法
		public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
		 			获取任意的方法,包含私有的
		参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
		返回获取多个方法:
		public Method[] getMethods() 获取本类与父类中所有public 修饰的方法
		public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)
	 */

		
	public static void main(String[] args) throws Exception {
		//
		Class c = Class.forName("demo1.Person");
		Constructor<Person> con = c.getConstructor();
		Person obj = con.newInstance();
		obj.setName("alex");
//		//获得共有方法
//		Method[] methods = c.getMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
//		System.out.println("----------------------");
//		//获得所有方法
//		methods = c.getDeclaredMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
		//获得指定方法
		Method method = c.getDeclaredMethod("sleep", int.class);
		//设置setAccessible
		method.setAccessible(true);
		//调用该函数
		method.invoke(obj, 10);
		method = c.getDeclaredMethod("eat");
		method.setAccessible(true);
		method.invoke(obj);
	}
}

  • 8 反射配置文件
package demo1;

import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;

public class Test8 {
	
	/*
	 * 反射配置文件
	 * 
	 * 通过反射配置文件,运行配置文件中指定类的对应方法
		读取Peoperties.txt文件中的数据,通过反射技术,来完成Person对象的创建
	 */
	
	public static void main(String[] args) throws Exception {
		//获得配置文件中的类与方法
		Properties pro = new Properties();
		pro.load(new InputStreamReader(
				Test8.class.getClassLoader().getResourceAsStream("config.properties")));
		Set<String> set = pro.stringPropertyNames();
		for (String key : set) {
			System.out.println(key+ "=" +pro.getProperty(key));
		}
		String className = pro.getProperty("className");
		String method = pro.getProperty("method");
		//获得Class对象
		Class c = Class.forName(className);
		//获得构造器
		Constructor	con = c.getDeclaredConstructor();
		//获得Object对象
		Object obj = con.newInstance();
		//获得指定方法
		Method newMethod = c.getDeclaredMethod(method);
		//取消类型检查
		newMethod.setAccessible(true);
		//执行方法
		newMethod.invoke(obj);
	}
}

  • 9 泛形擦除
package demo1;

import java.lang.reflect.Method;
import java.util.ArrayList;

public class Test9 {

	/*
	 * 泛型擦除
	 * 将已存在的ArrayList<Integer>集合中添加一个字符串数据,如何实现?
		其实程序编译后产生的.class文件中是没有泛型约束的,这种现象我们称为泛型的擦除。
		那么,我们可以通过反射技术,来完成向有泛型约束的集合中,添加任意类型的元素
	 * 
	 */
	
	public static void main(String[] args) throws Exception, SecurityException {
		
		ArrayList<String> list = new ArrayList<>();
		Class c = list.getClass();
		list.add("asdf");
		Method m = c.getMethod("add", Object.class);
		m.invoke(list, new Integer(124));
		System.out.println(list);
	}
	
}

       


  • Person 类
package demo1;

public class Person {
    private String name;
    private String sex;
    private int age;
    public String title;
    
    
    public Person() {}


    public Person(String name, String sex, int age, String title) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.title = title;
    }
    
    private Person(String name) {
        this.name = name;
    }
    
    private void eat() {
        System.out.println(name+"在吃饭...");
    }

    public String getName() {
        return name;
    }


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


    public String getSex() {
        return sex;
    }


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


    public int getAge() {
        return age;
    }


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


    public String getTitle() {
        return title;
    }


    public void setTitle(String title) {
        this.title = title;
    }


    @Override
    public String toString() {
        return "Person [name=" + name + ", sex=" + sex + ", age=" + age + ", title=" + title + "]";
    }


    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((sex == null) ? 0 : sex.hashCode());
        result = prime * result + ((title == null) ? 0 : title.hashCode());
        return result;
    }


    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (sex == null) {
            if (other.sex != null)
                return false;
        } else if (!sex.equals(other.sex))
            return false;
        if (title == null) {
            if (other.title != null)
                return false;
        } else if (!title.equals(other.title))
            return false;
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/alexzt/article/details/80431090
今日推荐