黑马程序员---Java基础---反射

-----------android培训java培训、java学习型技术博客、期待与您交流!------------ 


一、获取Class对象的三种方式:

1.调用Object类的getClass():任何类都会继承此方法;

2.任何的数据类型(包括基本类型)都有一个:静态的class属性:

Student.class;

int.class

3.调用Class类的静态方法forName(String 全名限定的类名):(常用)

通过这个Class对象,可以获取Student类内部的成员属性、构造方法、成员方法的一些信息,并能够调用它们;

package cn.hebei.sjz_反射;

/*
 * 获取Class对象的三种方式:
 */
public class Demo {
	public static void main(String[] args) throws Exception {
		Student stu = new Student();

		Class stuClass1 = stu.getClass();

		Class stuClass2 = Student.class;

		Class stuClass3 = Class.forName("cn.itcast.demo01_获取Class对象的三种方式.Student");

		System.out.println(stuClass1 == stuClass2);
		System.out.println(stuClass1 == stuClass3);

		Student stu2 = new Student();
		Class stuClass4 = stu2.getClass();
		System.out.println(stuClass1 == stuClass4);
	}
}


二、通过Class对象获取构造方法并调用
Class类:

批量的:

Constructor[] getConstructors() :获取所有的"公有构造方法"

Constructor[] getDeclaredConstructors() :获取全部(包括私有)的构造方法;

获取某个构造方法

Constructor getConstructor(Class ... parameterTypes) :获取指定的"公有构造方法";

Constructor getDeclaredConstructor(Class ... parameterTypes) :获取指定的构造方法(包括私有的);

调用某个构造方法:

Constructor的 Object newInstance(Object... initargs) :调用指定构造方法,并实例化此类的对象;

暴力访问:如果私有成员,需要设置暴力访问;

Constructor的setAccessible(true):不进行权限检查;

package cn.hebei.sjz_通过Class对象获取构造方法并调用;

import java.lang.reflect.Constructor;

public class Demo {
	public static void main(String[] args) throws Exception {
		//1.获取Student的Class对象
		Class stuClass = Class.forName("cn.itcast.demo02_通过Class对象获取构造方法并调用.Student");
		System.out.println("************获取所有的\"公有构造方法\"*******************");
		Constructor[] conArray = stuClass.getConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("************获取所有的构造方法(包括私有的)***************");
		conArray = stuClass.getDeclaredConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("************获取\"公有构造方法\"***********************");
		Constructor con = stuClass.getConstructor(String.class);//获取的是"具有String类型形参的"公有构造方法
	//	Constructor con = stuClass.getConstructor(String.class,int.class);
		Object obj = con.newInstance("刘德华");//调用此构造方法,并传递实参:相当于:Object obj = new Student("刘德华");
		
		System.out.println("************获取\"私有构造方法\"并调用*******************");
		con = stuClass.getDeclaredConstructor();
		//设置暴力访问
		con.setAccessible(true);
		
		obj = con.newInstance();
		
	}
}


三、通过Class对象获取成员属性并调用
Class类的方法:

批量的:

Field[] getFields():获取所有"公有属性";

Field[] getDeclaredFields() :获取所有成员属性(包括私有):

获取单个成员属性

Field getField(String name) :获取指定的"公有属性";

Field getDeclaredField(String name) :获取指定的属性,包括私有的;

为成员属性赋值:(注意:1.一定要先实例化此类对象;2.访问私有属性前,要设置暴力访问)

Field的 void set(Object obj, Object value) 

package cn.hebei.sjz_通过Class对象获取成员属性;

import java.lang.reflect.Field;

public class Demo {
	public static void main(String[] args) throws Exception {
		// 1.获取Student的Class对象
		Class stuClass = Class.forName("cn.itcast.demo03_通过Class对象获取成员属性并调用.Student");
		System.out.println("********************获取所有\"公有属性\"************************");
		Field[] fieldArray = stuClass.getFields();
		for (Field f : fieldArray) {
			System.out.println(f);
		}
		System.out.println("********************获取所有属性(包括私有的)************************");
		fieldArray = stuClass.getDeclaredFields();
		for (Field f : fieldArray) {
			System.out.println(f);
		}

		// 创建一个Student对象
		Object obj = stuClass.getConstructor().newInstance();
		System.out.println("*********************获取公有属性,并调用*********************************");
		Field f = stuClass.getField("name");
		System.out.println("赋值前打印:" + obj);
		f.set(obj, "刘德华");
		System.out.println("赋值后打印:" + obj);

		System.out.println("*********************获取私有属性,并赋值*********************************");
		f = stuClass.getDeclaredField("score");
		// 暴力访问
		f.setAccessible(true);

		f.set(obj, 88.5);
		System.out.println(obj);
	}
}


四、通过Class对象获取成员方法并调用
Class类的方法:

批量的:

Method[] getMethods():获取所有"公有方法"(包括继承的)

Method[] getDeclaredMethods() :获取所有成员方法(包括私有):

获取单个成员方法

Method getMethod(String name, Class... parameterTypes) :获取指定的"公有方法";

Method getDeclaredMethod(String name, Class... parameterTypes) :获取指定的方法,包括私有的;

调用方法:(注意:1.要先创建此类的对象;2.调用私有方法前,要先设置暴力访问)

Method:

Object invoke(Object obj, Object... args) :调用Method所代表的方法:

返回值:此Method对象调用所代表的方法,所获取的返回值;

形参:obj:方法所属对象;

args:Method所代表的那个方法的实参列表;

package cn.hebei.sjz_通过Class对象获取成员方法并调用;

import java.lang.reflect.Method;

public class Demo {
	public static void main(String[] args) throws Exception {
		//1.获取Class对象
		Class stuClass = Class.forName("cn.itcast.demo04_通过Class对象获取成员方法并调用.Student");
		System.out.println("*************获取所有\"公有方法\"*******************");
		Method[] methodArray = stuClass.getMethods();
		for(Method m : methodArray){
			System.out.println(m);
		}
		System.out.println("**************获取所有的方法(包括私有的)***************");
		methodArray = stuClass.getDeclaredMethods();
		for(Method m : methodArray){
			System.out.println(m);
		}
		
		//创建Student对象
		Object obj = stuClass.getConstructor().newInstance();
		
		System.out.println("**************获取公有的,带参的show1()方法,并调用******");
		Method m = stuClass.getMethod("show1", String.class,int.class);
		Object result = m.invoke(obj, "刘德华",20);//调用show1()方法
		System.out.println("调用的返回值:" + result);
		
		System.out.println("***************获取私有的,无参的、无返回值的show4()方法,并调用****************");
		m = stuClass.getDeclaredMethod("show4");
		m.setAccessible(true);
		m.invoke(obj);
		
		
	}
}


五、练习

练习1

package cn.hebei.sjz_通过反射运行配置文件内容;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
/*
 * 通过反射运行配置文件内容
 */
public class Demo {
	public static void main(String[] args) throws Exception {
		//1.获取Student的Class对象
	//	Class stuClass = Class.forName("cn.hebei.sjz_通过反射运行配置文件内容.Student");
		String classPath = getValue("className");
		Class stuClass = Class.forName(classPath);
		
		//2.实例化一个Student对象
		Object obj = stuClass.getConstructor().newInstance();
		//3.调用方法
	//	Method m = stuClass.getMethod("show");
		Method m = stuClass.getMethod(getValue("methodName"));
		m.invoke(obj);
	}
	
	//一个方法,获取配置文件中的某个键对应的值
	public static String getValue(String key) throws IOException{
		Properties pro = new Properties();
		FileReader in = new FileReader("properties.ini");
		pro.load(in);
		in.close();
		
		return pro.getProperty(key);
	}
}


练习2:

package cn.hebei.sjz_通过反射越过泛型检查;

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

/*
 * 
 * 通过反射越过泛型检查:
 * 
 * 1.定义一个具有String泛型的集合,要求成功向集合中添加一个int数据;
 */
public class Demo {
	public static void main(String[] args) throws Exception, SecurityException {
		List<String> strList = new ArrayList<>();
		strList.add("aaa");
		strList.add("bbb");
	//	strList.add(10);
		
		//通过反射
		Class listClass = strList.getClass();
		//获取add方法
		Method addMethod = listClass.getMethod("add", Object.class);
		//调用add方法
		addMethod.invoke(strList, 10);
		
		//遍历集合
		for(Object o : strList){
			System.out.println(o);
		}
		
	}
}


练习3:

package cn.hebei.sjz_通用方法;

import java.lang.reflect.Field;

/*
 * 通用方法
 */
public class Demo {
	public static void main(String[] args) throws SecurityException, Exception {
		Cat c = new Cat();
		setValue(c, "name", "波斯猫");
		c.show();
	}

	// 通过反射写一个通用的设置某个对象的某个属性为指定的值
	public static void setValue(Object target, String fieldName, Object value)
			throws Exception, SecurityException {
		// 1.获取Class对象
		Class aClass = target.getClass();
		// 2.获取字段
		Field f = aClass.getDeclaredField(fieldName);
		// 3.暴力访问
		f.setAccessible(true);
		// 4.设置
		f.set(target, value);
	}
}


六、代理模式

代理类的目的:是为所代理的类的某些方法,增加一些额外的操作;

Java中实现动态代理:

步骤:

1.自定义类,实现InvocationHandler接口;

重写invoke()方法:需要代理的方法,都要经过此方法,

我们可以在此方法中做我们想要做的事情;

2.动态生成代理对象:

Proxy类静态方法:newProxyInstance()

注意:Java的动态代理机制是基于"接口"的,也就是所有需要被代理的类都必须实现某个接口,以达到它们作为共同类型的目的;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值