java中的反射机制Reflect

1.反射机制有什么用呢?
	通过java语言中的反射机制可以操作字节码文件
	让程序更加灵活
2.反射机制的相关类在哪一个包下?
	java.lang.reflect.*
3.反射机制相关的类有哪些?
	java.lang.Class	字节码文件
	java.lang.reflect.Method	字节码中的方法字节码
	java.lang.reflect.Constructor	字节码中的构造方法字节码
	java.lang.reflect.Field	字节码中的属性字节码
4.在java中获取Class的三种方式
	1.Class.forName("完整类名带包名")
	2.Class c = 对象.getClass()
	3.Class c = 任何类型.class
5.获取了Class之后,可以调用无参数构造方法来实例化对象
	//c是一个User类型
	Class c = Class.forName("bean.User");
	
	//实例化一个User类型的对象
	Object obj = c.newInstance();
	
	//底层会调用User这个类的无参数构造方法,完成对象的创建
	//必须保证User的无参数构造方法是存在的,否则会出现"实例化异常"
6.希望一个类的静态代码块执行,其他不执行:
	使用Class.forName(这个类的完整类名),在执行时类会加载
7.IO + Properties怎么快速绑定属性配置文件
	java.util.ResourceBundle包下提供了一个资源绑定器,便于获取配置文件中的信息
	//资源绑定器只能绑定xxx.properties文件,并且文件必须在类路径下(必须省略后缀)
	
	ResourceBundle bundle = ResourceBundle.getBundle("xxx");
	System.out.println(bundle.getString("key"));
8.关于JDK中自带的类加载器(了解)
	1.什么是类加载器?
		专门负责加载类的命令/工具
		ClassLoader
	2.JDK中自带了三个类加载器
		代码在开始执行之前,会将所需要类全部加载到JVM中
		java为了保证类加载的安全,使用了双亲委派机制
			按照加载的优先级依次加载,每当加载不到时才进行下一次加载
			1.启动类加载器	C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar(JDK最核心的类库)
			2.扩展类加载器	C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\*.jar
			3.应用类加载器	 classpath中的jar包(class文件)

一图流:
在这里插入图片描述

1.获取一个类的字节码class的方法

	要操作一个类的字节码,首先需要获取这个类的字节码,如何获取呢?
	三种方式
		1.Class.forName("完整类名带包名")
		2.Class c = 对象.getClass()
		3.Class c = 任何类型.class
package reflect;

import java.util.Date;

public class ReflectTest01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
			1.Class.forName()
				1.静态方法
				2.方法的参数是一个字符串
				3.字符串需要的是一个完整类名
				4.完整类名必须带有包名
		 */
		Class c1 = null;
		Class c2 = null;
		Class c3 = null;
		Class c4 = null;
		try {
			c1 = Class.forName("java.lang.String");//String.class文件/String类型
			c2 = Class.forName("java.util.Date");
			c3 = Class.forName("java.lang.Integer");
			c4 = Class.forName("java.lang.System");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//2.java中任何一个对象都有一个方法:getClass()
		String s = "abc";
		Class x = s.getClass();
		System.out.println(c1 == x);//true,内存地址相同
		
		Date time = new Date();
		Class y = time.getClass();
		System.out.println(c2 == y);//true,变量中保存的内存地址都是一样的,都指向方法区中的字节码
		
		//3.java语言中任何一个类都有.class属性
		Class z = String.class;//String类型
		Class k = Date.class;//Date类型
		Class f = int.class;
		Class e = double.class;
	}

}

2.在获取了class之后我们可以做什么

package reflect;

import bean.User;

public class ReflectTest02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//不使用反射机制来创建对象
		User user = new User();
		System.out.println(user);
		
		//通过反射机制获取class,从而实例化对象
		try {
			Class c = Class.forName("bean.User");
			Object obj = c.newInstance();
			//底层会调用User这个类的无参数构造方法,完成对象的创建
			//必须保证User的无参数构造方法是存在的
			System.out.println(obj);//bean.User@6108b2d7
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

3.剖析Class.forName()发生了什么?

类会加载
希望一个类的静态代码块执行,其他不执行:
	使用Class.forName(这个类的完整类名)
package reflect;

public class ReflectTest04 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			Class.forName("reflect.MyClass");//类会加载
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
class MyClass{
	//静态代码块在类加载时执行,并且只执行一次
	static {
		System.out.println("MyClass的静态代码执行了");
	}
}

4.※怎么通过反射机制访问一个java对象的属性?

必须掌握:
	怎么通过反射机制访问一个java对象的属性?
		1.获取对象
		2.获取属性值get
		3.给属性赋值set
	反射机制虽然让代码复杂了,但是为了“灵活”,这也是值得的
package bean;
//反射属性Field
public class Student {
	//Field翻译为字段,其实就是属性/成员
	//4个Field,分别采用了不同的访问控制权限修饰符
	public int no;
	private String name;
	protected int age;
	boolean sex;
	public static final double MATH_PI = 3.1415926;
}

package reflect;

import java.lang.reflect.Field;

import bean.Student;

public class ReflectTest07_Focus {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		//不使用反射机制,怎么访问一个对象的属性
		Student s = new Student();
		//赋值
		s.no = 1111;
		//读取
		System.out.println(s.no);
		
		//使用反射机制,访问对象属性
		Class c = Class.forName("bean.Student");
		Object obj = c.newInstance();//obj是Student对象(调用无参数构造方法)
		//获取no属性(根据属性名称)
		//c.getField("sex");//这种方式只能获取public属性
		Field noField = c.getDeclaredField("no");
		//给obj对象的no属性赋值
		noField.set(obj, 2222);
		//读取属性值
		System.out.println(noField.get(obj));
		
		//可以访问私有数据吗
		//获取
		Field nameField = c.getDeclaredField("name");
		//打破封装(反射机制的缺点:在外部可以访问private)
		nameField.setAccessible(true);
		//赋值
		nameField.set(obj, "jackson");
		System.out.println(nameField.get(obj));
		
		
	}

}

5.※怎么通过反射机制调用方法?

重点:通过反射机制怎么去调用方法
	要素分析:
		1.对象userService
		2.login方法名
		3.实参列表
		4.返回值
	作用:
		代码具有通用性
package bean;
/**
 * 	用户业务类
 * @author 余晖
 *
 */
public class UserService {

	/**
	 * 	登录方法
	 * @param name 用户名
	 * @param password 密码
	 * @return true表示登录成功,false表示登录失败
	 */
	public boolean login(String name,String password) {
		if("admin".equals(name)&&"123".equals(password)) {
			return true;
		}
		return false;
	}
	
	/**
	 * 	退出系统的方法
	 */
	public void logout() {
		System.out.println("系统已经安全退出!");
	}
}

package reflect;

import java.lang.reflect.Method;

import bean.UserService;


public class ReflectTest10_Focus {
	public static void main(String[] args) throws Exception{
		//不使用反射机制,调用方法
		//创建对象
		UserService userService = new UserService();
		//调用方法
		boolean loginSuccess = userService.login("admin", "123");
		System.out.println(loginSuccess?"登录成功":"登录失败");
		
		//使用反射机制来调用方法
		Class userServiceClass = Class.forName("bean.UserService");
		//创建对象
		Object obj = userServiceClass.newInstance();
		//获取method
		Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class,String.class);
		//调用方法※
		/**
		 * 1.obj
		 * 2.loginMethod
		 * 3."admin", "123"
		 * 4.retVlaue
		 */
		Object retValue = loginMethod.invoke(obj, "admin", "123");
	}
}

6.通过反射机制访问构造方法创建对象

package bean;

public class Vip {
	int no;
	String name;
	String birth;
	boolean sex;
	public Vip() {
		
	}
	public Vip(int no) {
		this.no = no;
	}
	public Vip(int no, String name) {
		this.no = no;
		this.name = name;
	}
	public Vip(int no, String name, String birth, boolean sex) {
		this.no = no;
		this.name = name;
		this.birth = birth;
		this.sex = sex;
	}
	@Override
	public String toString() {
		return "Vip [no=" + no + ", name=" + name + ", birth=" + birth + ", sex=" + sex + "]";
	}
}

package reflect;

import java.lang.reflect.Constructor;

import bean.Vip;

/**
 * 比上一个例子重要一点
 * 通过反射机制访问构造方法创建对象
 * @author 余晖
 *
 */
public class ReflectTest12 {
	public static void main(String[] args) throws Exception{
		//不使用反射机制怎么创建对象
		Vip v1 = new Vip();
		Vip v2 = new Vip(110,"zhangsan","2000-01-12",true);
		
		//使用反射机制怎么创建对象
		Class c = Class.forName("bean.Vip");
		//调用无参数构造方法
		Object o1 = c.newInstance();
		System.out.println(o1);
		//调用有参数构造方法
		//1.获取有参数的构造方法Constructor
		Constructor con = c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
		//2.调用构造方法new对象
		Object o2 = con.newInstance(110,"zhangsan","2000-01-12",true);
		System.out.println(o2);
		
		//获取无参数构造方法
		Constructor con2 = c.getDeclaredConstructor();
		Object o3 = con2.newInstance();
		System.out.println(o3);
	}
}

7.获取一个类的父类和实现的接口

package reflect;

public class ReflectTest13 {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		//String举例
		Class stringClass = Class.forName("java.lang.String");
		//获取父类
		System.out.println(stringClass.getSuperclass().getName());
		//获取接口(多个接口)
		Class[] interfaces = stringClass.getInterfaces();
		for(Class in : interfaces) {
			System.out.println(in.getName());
		}
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值