JavaSE高级部分之反射

反射

什么是反射:

  • 反射就是通过获取类的字节码文件对象:Class
  • 创建该类的实例(通过构造方法:Constroctor类),调用成员方法(Method类),
  • 给成员变量赋值(Field类)

获取字节码文件的方式有几种

三种方式

  • 1)Object类的getClass():表中正在运行的Java类(当前类字节码文件)
  • 2)任意Java类型的.class属性
  • 3)反射Class类中forName(“类或者接口的全限定名称”) ;
  • com.XXXXX.reflect_10.ReflectDemo

举例:

public class Person {
	
	//属性
	private String name ;//私有的属性
	int age ;
	public String address ;//地址
	
	
	//一些列构造方法
	public Person() {}
	
	private Person(String name) {
		this.name = name ;
	}
	
	Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	
	public Person(String name,int age,String address) {
		this.name = name ;
		this.age = age ;
		this.address = address ;
	}
	
	//成员方法
	public void show() {
		System.out.println("show person");
	}
	
	public String method(int num) {
		return "helloJavaEE"+num ;
	}
	
	private  void function(String str) {
		System.out.println(str);
	}
	
	public void function2() {
		System.out.println("helloJavaEE,i'm coming...");
	}
}
public class ReflectDemo {
	
	public static void main(String[] args) throws Exception {
		
		//创建两个Person对象
		Person p1 = new Person("美女", 22) ;
		Person p2 = new Person("美女", 22) ;
		
		System.out.println(p1==p2);//false
		System.out.println(p1.getClass()==p2.getClass());
		Class c1 = p1.getClass() ; //class com.qianfeng.reflect_10.Person
		Class c2 = p2.getClass() ;
		System.out.println(c1==c2);
		
		System.out.println("--------------------------");
		
		//方式2:获取字节码文件
		Class c3 = Person.class ;
		System.out.println(c3);//class com.qianfeng.reflect_10.Person
		Class c4 = Person.class ;
		System.out.println(c3==c4);
		
		System.out.println("----------------------------");
		
		//方式3:获取类的字节码文件对象
		//public static Class<?> forName(String className)

		Class c5 = Class.forName("com.qianfeng.reflect_10.Person") ;
		System.out.println(c5);//class com.qianfeng.reflect_10.Person
		//推荐:第三种:里面参数一个字符串:可以放在配置文件中使用!
	}
}

之前的写法

  • Person p = new Person();通过无参构造方法创建对象
  • Person p = new Person(“美女”); 形参String—String类型字节码文件格式-> java.lang.String

使用反射获取构造方法并使用,(Constructor)

Class 类的实例表示正在运行的 Java 应用程序中的类和接口

public class ReflectDemo {
	
	public static void main(String[] args) throws Exception {
		
		//获取Person类的字节码文件对象
		//public static Class<?> forName(String className)
		Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
		
		//获取构造方法(构造器)对象
		//public Constructor<?>[] getConstructors():表示获取当前类中的所有的公共的构造方法
		//public Constructor<?>[] getDeclaredConstructors():
		//获取当前类中所有的构造方法:包括私有的,公共的,默认,受保护的(proteted)
		/*
		Constructor[] cons = c.getConstructors() ;
		for(Constructor con: cons) {
			System.out.println(con);
			/**
			 * public com.qianfeng.reflect_01.Person(java.lang.String,int,java.lang.String)
			   public com.qianfeng.reflect_01.Person(
			 */
		//}
		/*
		Constructor[] cons = c.getDeclaredConstructors() ;
		for(Constructor con: cons) {
			System.out.println(con);
		}
		*/
		/**
		 * public com.qianfeng.reflect_01.Person(java.lang.String,int,java.lang.String)
		com.qianfeng.reflect_01.Person(java.lang.String,int)
		private com.qianfeng.reflect_01.Person(java.lang.String)
		public com.qianfeng.reflect_01.Person()
		 */
		
		//获取某一个构造方法所在对象:Constructor
		//public Constructor<T> getConstructor(Class<?>... parameterTypes)
		//获取指定的公共构造方法
		//参数:parameterTypes可变参数  里面相当于数组
		//参数是当前的字节码文件Class
		
		//Person p = new Person();通过无参构造方法创建对象 
		//直接输出p----->如果重写toString():成员信息的表达式 
		
		Constructor con = c.getConstructor() ;//Person类的无参构造方法
		
		
		//System.out.println(con);//public com.qianfeng.reflect_01.Person()
		
		//通过构造器如何获取当前Person类的实例
		//Constructor创建该类的实例
		//public T newInstance(Object... initargs):参数为当前实际参数
		Object obj = con.newInstance() ;
		System.out.println(obj);//p
		
		System.out.println("--------------------");
		
		Person p = new Person() ;
		System.out.println(p);

	}
	
	//...:jdk5提供的可变参数 相当于数组
	public static void add(int...a) {
		
	}
}

之前的写法

  • Person p = new Person(“美女”) ;
  • System.out.println§ ; toString()
public class ReflectDemo {
	
	public static void main(String[] args) throws Exception{
		
		//获取Person类的字节码文件
		Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
		
		//获取单个的构造方法
		//Person(String) :是一个私有的,不是公共的
//		public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	
		//获取指定的构造方法
		//Constructor con  = c.getDeclaredConstructor(String.class) ;
		
		//获取单三个参数的构造方法
		Constructor con = c.getConstructor(String.class,int.class,String.class) ;
		
		//public void setAccessible(boolean flag):参数为true,取消java语言访问检查
		con.setAccessible(true);

		//取消Java语言的访问检查
		//非法访问异常:
		//java.lang.IllegalAccessException: Class com.qianfeng.reflect_02.ReflectDemo can not access a member of 
				//class com.qianfeng.reflect_01.Person with modifiers "private"
		//创建该类实例
		Object obj = con.newInstance("美女",27,"西安市鄠邑区") ;
		System.out.println(obj);
		//Person [name=美女, age=27, address=西安市鄠邑区]
		
	}
}

之前的写法:

  • Person p = new Person() ;
  • p.字段名(属性名) = “赋值”;
  • 通过反射获取成员变量Field并使用
public class ReflectDemo2 {
	
	public static void main(String[] args) throws Exception {
		
		//获取Person类字节码文件对象
		Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
		
		//获取构造器:Constructor:无参构造方法
		Constructor con = c.getConstructor() ;// public com.qianfeng.reflect_01.Person(){}
		
		//创建该类实例
		Object obj = con.newInstance() ; //p对象
		
		//获取成员变量
		//public Field[] getDeclaredFields():获取所有的Field成员变量(公共的,私有的,默认的,受保护的)
		//public Field[] getFields():获取所有的公共的字段
		//Field[] fields = c.getDeclaredFields() ;
		/*
		Field[] fields = c.getFields() ;
		for(Field f : fields) {
			System.out.println(f);
		}
		*/
		
		//给name进行赋值  private String name;
		//public Field getDeclaredField(String name)
		//参数为:字段名(属性)
		Field field = c.getDeclaredField("name") ;
		//取消Java语言访问检查
		field.setAccessible(true);
		
		//public void set(Object obj,Object value)
		//参数1:当前该Person类的实例
	
		//参数2:给当前成员字段"name"设置的内容
		
		field.set(obj, "美女"); // 相当于:p.name = "美女"
		System.out.println(obj);
		//Person [name=美女, age=0, address=null]
		
		System.out.println("-------------------");
		
		//age,address进行赋值

	}
}

之前的写法:

  • 通过无参构造方法创建对象
  • Person p = new Pereson() ;
  • p.show();
  • 使用反射获取Person类的字节码文件对象,并获取成员方法Method并使用
@SuppressWarnings("all") //压制警告
public class ReflectDemo3 {
	
	public static void main(String[] args) throws Exception {
		//获取Person类的字节码文件对象
		Class c = Class.forName("com.qianfeng.reflect_01.Person") ;
		
		//获取该类的无参构造方法
		Constructor con = c.getConstructor() ;
		//创建该类的实例
		Object obj  = con.newInstance() ;
		
		//通过获取成员方法
		//public Method[] getDeclaredMethods():获取所有的方法:仅限本类,不包括继承的
		//public Method[] getMethods():获取所有的公共的成员方法:不仅有本类的,还有它父类的
//		Method[] methods = c.getDeclaredMethods() ;
		/*
		Method[] methods = c.getMethods() ;
		for (Method method : methods) {
			System.out.println(method);
		}
		*/
		
		
		
		//public Method getDeclaredMethod(String name,
		//Class<?>... parameterTypes)获取指定的方法
		//public Method getMethod(String name,Class<?>... parameterTypes)
		//获取公共的成员方法
		//参数1:方法名
		//参数2:当前如果该方法有形式参数,跟上行驶时参数类型的Class
		Method m = c.getMethod("show") ;
		//Method类:
		//底层调用方法
		//public Object invoke(Object obj, Object... args)
		//参数1:当前类的实例
		//参数2:跟的实际参数
		m.invoke(obj) ; // 相当于 之前:使用对象名p.show();
		/*
			System.out.println("-------------------");
			Person p = new Person() ;
			p.show();
		*/
		System.out.println("-----------------------------------");
		
		/**
		 * public String method(int num) {
					return "helloJavaEE"+num ;
			}
		 */
		Method m2 = c.getMethod("method", int.class) ;
		Object object	 = m2.invoke(obj, 100) ;
		System.out.println(object);
		
		System.out.println("-------------------------------------");
		/**
		 * private  void function(String str) {
				System.out.println(str);
			}
		 */
		Method m3 = c.getDeclaredMethod("function", String.class) ;
		//取消Java语言访问检查
		m3.setAccessible(true);
		
		m3.invoke(obj, "hello,张佳宁") ;	
	}
}

如何读取src目录下的properties配置文件

class.properties

className=com.qianfeng.reflect_03.Student
methondName=love
public class Test2 {
	
	public static void main(String[] args) throws Exception {
		
		//1)读取src下面的class.properties配置文件
		//获取当前类的类加载器
		//Class
		//public ClassLoader getClassLoader()
		ClassLoader classLoader = Test2.class.getClassLoader() ;
		//public InputStream getResourceAsStream(String name)
		//读取指定资源的输入流   
		//参数是文件名称  文件必须是在src目录下(类路径)
		//方式1
		InputStream inputStream = classLoader.getResourceAsStream("class.properties") ;
		//方式2:通过类加载器获取网络资源地址对象:URL
		//public URL getResource(String name)
		//public String getPath()
		
		//创建属性集合类对象
		Properties prop = new Properties() ;
		//将流中的数据加载到属性集合类中
		prop.load(inputStream);
		
		//System.out.println(prop);//className=com.qianfeng.reflect_03.Worker, methondName=love}
		//通过键的名称获取值
		String className = prop.getProperty("className") ;
		String methodName = prop.getProperty("methondName") ;
		
		//获取当前类的Class
		Class c	 = Class.forName(className) ;
		
		//直接获取该类实例
		Object obj = c.newInstance() ;
		//获取Method成员方法
		Method m = c.getMethod(methodName) ;
		
		m.invoke(obj) ;
	}
}

需求:有一个ArrayList集合,需要给里面添加String类型的数据,如何实现呢?

public class Test3 {

	public static void main(String[] args) throws Exception{
		
		//创建ArrayList<Integer>集合
		ArrayList<Integer> array = new ArrayList<Integer>() ;
		
		//添加元素
		array.add(100) ;
		array.add(200) ;
		//array.add("javaee") ;
		//array.add("hello") ;
		
		//获取类的字节码文件对象有三种
		//直接获取arrayList集合的字节码文件对象
		Class clazz = array.getClass() ;
		//System.out.println(c);//class java.util.ArrayList
		
		//获取当前Method类对象:成员方法
		//public boolean add(Object e) 
		Method m = clazz.getMethod("add", Object.class) ;
		
		//调用add方法
		m.invoke(array, "hello") ;
		m.invoke(array, "world") ;
		
		System.out.println(array);
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值