黑马程序员——反射

------- android培训java培训、期待与您交流! ----------

  JAVA之反射

一、反射的概述
JAVA反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能掉用他的任意方法和属性。要想获取字节码文件,就要通过Class类的方法来获取。

二、Class类
Class类:
成员变量 Field
成员方法 Constructor
成员方法 Method

获取class文件对象的方式:
1、通过 对象.class获取
2、通过 类名.class获取
3、通过 Class.forName(String name)获取


1、获取Class对象
获取Class对象代码:
package it.heima.reflect;

public class ClassDemo1 {
	public static void main(String[] args) throws Exception {
		Person p1=new Person();
		Person p2=new Person();
		//方式一:对象.getClass()
		Class p1Class=p1.getClass();
		Class p2Class=p2.getClass();
		System.out.println(p1==p2);
		System.out.println(p1Class==p2Class);
		System.out.println("------------------------");
		//方式二 类名.class
		Class p3Class=Person.class;
		Class p4Class=Person.class;
		System.out.println(p3Class==p4Class);
		System.out.println("------------------------");
		//方式三:Class.forName()
		Class p5Class=Class.forName("it.heima.reflect.Person");
		Class p6Class=Class.forName("it.heima.reflect.Person");;
		System.out.println(p5Class==p6Class);
		
	}
}

2、获取构造方法
通过反射获取构造方法并使用:
获取构造函数的方法:
getConstructor(Class<?> ...para) 根据可变参数获取单个公共构造,要传入class文件,如int.class,String.class
getConstructors() 获取所有公共的构造函数,非公共的不能获取
getDeclaredConstructors() 获取所有申明的构造,包括私有的
通过构Class对象创建对象
newInstance() 根据null构造创建一个对象

使用无参的构造函数代码演示:
package it.heima.reflect;

import java.lang.reflect.Constructor;

public class ConstructDemo {
	public static void main(String[] args) throws Exception {
		Class c=Class.forName("it.heima.reflect.Person");
		//Constructor[] constructors=c.getConstructors();	//获取所有Public构造
		/*Constructor[] constructors=c.getDeclaredConstructors();	//获取所有申明的构造,包括私有的,不包括父类的
		for(Constructor cc:constructors){
			System.out.println(cc);
		}*/
		Constructor cc=c.getConstructor(String.class,int.class,int.class);//只能获取单个Publicd的构造
		System.out.println(cc);
		
		Object obj=c.newInstance();
		Person p=(Person)obj;
		p.show();
		System.out.println(obj);
	}
}
newInstance()有异常存在,当无参构造是private时,存在一个异常, IllegalAccessException - 如果该类或其 null 构造方法是不可访问的。

使用带参的构造函数代码演示:
package it.heima.reflect;

import java.lang.reflect.Constructor;

public class ConstructorDemo2 {
	public static void main(String[] args) throws Exception {
		Class c=Class.forName("it.heima.reflect.Person");
		Constructor con=c.getConstructor(String.class,int.class,int.class);
		Object obj=con.newInstance("张三",20,200000);
		System.out.println(obj);
	} 
}
注:Class和Constuctor类都有newInstance(),Class类的只能创建非私有的无参构造,Constuctor的newInstance可以创建带参的对象。

使用私有的构造函数代码演示:
package it.heima.reflect;

import java.lang.reflect.Constructor;

public class ConstructorDemo3 {
	public static void main(String[] args) throws Exception{
		Class c=Class.forName("it.heima.reflect.Person");
		Constructor cc=c.getDeclaredConstructor(String.class);
		cc.setAccessible(true);//暴力反射
		Object obj=cc.newInstance("张三");
		System.out.println(obj);
	}
}
获取到私有的构造函数后,不能创建对象,否则有异常出现
IllegalAccessException - 如果此 Constructor 对象实施 Java 语言访问控制并且底层构造方法是不可访问的。 
需要设置该构造的权限。(暴力反射
setAccessible(boolean)---------->true
然后才能创建对象。

3、获取成员变量
获取成员变量类的方法:
getField(String name)
getDeclaredField(String name)
getFields()
成员变量的方法:
set(Object obj,value)
get(Object obj)
setAccessible(boolean)
成员变量的使用代码演示:
package it.heima.reflect;

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

public class GetFieldDemo {
	public static void main(String[] args) throws Exception{
		Class c=Class.forName("it.heima.reflect.Person");
		/*//Field[] field=c.getFields(); 	获取所有公共的成员
		//Field[] field=c.getDeclaredFields();	获取所有申明的成员
		for(Field f:field){
			System.out.println(f);
		}*/
		Constructor cc=c.getDeclaredConstructor();
		
		Object o=cc.newInstance();
		Field field=c.getDeclaredField("age");
		field.setAccessible(true);
		field.set(o, 20);
		Field field2=c.getDeclaredField("name");
		field2.set(o, "张三");
		
		Field field3=c.getDeclaredField("salary");
		field3.set(o, 2000);
		
		System.out.println(o);
	}
}
注:成员变量一般是私有的,要注意Field.setAccessible(true);

3、获取并使用成员方法
获取成员变量类的方法:
getMethod(String name,class<?>...)
getDeclared Method (String name,class<?>..)
getDeclared Methods() 获取所有自己的方法
get Methods() 获取所有的公共方法,包括父亲的

成员变量的获取和使用代码演示:
package it.heima.reflect;

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

public class MethodDemo {
	public static void main(String[] args) throws Exception{
		Class c=Class.forName("it.heima.reflect.Person");
	/*	//Method[] method=c.getMethods();	//获取所有公共的方法,包括父类的
		Method[] method=c.getDeclaredMethods();	//获取所有自身的方法
		for(Method item:method){
			System.out.println(item);
		}*/
		Constructor constructor=c.getDeclaredConstructor();
		Object obj=constructor.newInstance();
		
		Method method=c.getDeclaredMethod("show");
		method.invoke(obj);//调用obj的method方法
		
		Method method2=c.getDeclaredMethod("method",String.class);
		method2.setAccessible(true);
		method2.invoke(obj, "你好");
		
		Method method3=c.getDeclaredMethod("stringMethod",String.class);
		method3.setAccessible(true);
		Object s=method3.invoke(obj, "我的");
		System.out.println(s);
	}
}

三、配置文件的应用
1、通过配置文件调用方法
package it.heima.reflect;


import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class PropertiesDemo {
	//通过配置文件调用方法
	public static void main(String[] args) throws Exception {
		Properties properties=new Properties();
		FileReader fileReader=new FileReader("E:\\JavaSE_WorkSpace\\AllTest\\src\\it\\heima\\reflect\\Properties.txt");
		properties.load(fileReader);
		fileReader.close();
		
		String className=properties.getProperty("className");
	
		String methodName=properties.getProperty("methodName");
		
		Class c=Class.forName(className);
		Constructor con=c.getDeclaredConstructor();
		con.setAccessible(true);
		Object obj=con.newInstance();
		Method method=c.getDeclaredMethod(methodName);
		method.setAccessible(true);
		method.invoke(obj);
	}
}

2、通过反射绕过泛型
package it.heima.reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;
//通过泛型绕开
public class GenericityDemo {
	public static void main(String[] args) throws Exception {
		ArrayList<Integer> arrayList=new ArrayList<>();
		Class c=ArrayList.class;
		Method method=c.getMethod("add", Object.class); //泛型默认是Object类型的,这是一个泛型方法。如果传入其他类型会出现异常,NoSuchMethod
		method.invoke(arrayList, "hello");
		
		System.out.println(arrayList);
		
	}
}
注意:getMethod()时要注意参数的类型,否则有NoSuchMethodException


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值