1. 反射机制
1.1、 反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。
优点类似于黑客。( 可以读和修改字节码文件。)
通过,反射机制可以操作代码片段。(class文件。 )
1.2、反射机制的相关类在哪个包下?
java. lang. reflect. *;
1.3、反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码,代表一个类型
java.lang.reflect.Method:代表字节码中的方法字节码。,
java.lang.reflect.Constructor:代表字节码中的构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码,代表类中的成员变量(静态变量)
java. langr.Class:
public class User {
// Field
int no;
// Constructor
public User() {
}
public User (int no) {
this.no = no;
}
// Method
public void setNo (int no) {
this.no = no;
}
public int getNo() {
return no;
}
}
package 反射;
/*
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java. lang. Class实例?
三种方式
第一种:Class c = Clasd.forName( "完整类名带包名");
第二种:Class c =对象. getClass();
第三种:Class c =任何类型.class;
*/
import java.util.Date;
public class 获取Class的三种方式 {
public static void main(String[] args) {
/*Class. forName()
1、静态方法
2、方法的参数是一个字符串。
3、字符串需要的是一个完整类名。
4、完整类名必须带有包名。java. lang包也不能省略。*/
Class c1=null;
Class c2=null;
Class c3=null;
Class c4=null;
try {
c1=Class.forName("java.lang.String");//c1代表String.class文件,或者说C1代表String类型
c2=Class.forName("java.lang.Integer");//c2代表Integer类型
c3=Class.forName("java.lang.System");
c4=Class.forName("java.util.Date");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
String s="abc";
Class x=s.getClass();//x代表String.class字节码文件,代表String类型
System.out.println(x==c1);//==判断的是对象的内存地址。true
Date date=new Date();
Class y=date.getClass();
System.out.println(y==c4);//true(c2与y两个变量保存的内存地址都是一样的都指向方法区中的字节码文件)。
//第三种方式, java语言中任何-种类型,包括基本数据类型,它都有. class属性。
Class z = String.class; // z代表String类型
Class k = Date.class; // k代表Date类型
Class f = int.class; // f代表int类型
Class e = double.class; // e代表double类型
System.out.println(x == z); // true
System.out.println(z);
}
}
2.资源绑定器
import java.util.ResourceBundle;
/* java.util包下提供了- -个资源绑定器,便于获取属性配置文件中的内容。
使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下。
来*/
public class 资源绑定器 {
public static void main(String[] args) {
//资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下。文件扩展名必须也是properties
//并且在写路径的时候,路径后面的扩展名不能写
ResourceBundle bundle=ResourceBundle.getBundle("classinfo2");
String className=bundle.getString("className");
System.out.println(className);
}
}
3、关于JDK中自带的类加载器:
3.1、什么是类加载器?
专门负贲加载类的命令/工具。
ClassLoader
3.2、 JDK中自带了3个类加载器
启动类加载器:rt.jar
扩展类加载器:ext/*. jar
应用类加载器:classpath
3.3、假设有这样一段代码:
string s = “abc” ;
代码在开始执行之前,会将所需要类全部加载到JVM当中。
通过类加载器加载,看到以上代码类加载器会找String.class
文件,找到就加载,那么是怎么进行加载的呢?
首先通过"启动类加载器”加载。
注意:启动类加载器专门加载: C: \Program Files\Java\jdk1. 8
rt. jar中都是JDK最核心的类库。
如果通过"启动类加载器”加载不到的时候,
会通过"扩展类加载器”加载。
注意:扩展类加载器专门加载: c: \Program Files\Java\jdk1. 8
如果扩展类加载器"没有加载到,那么
会通过\应用类加载器"加载。
注意:应用类加载器专门加载:classpath中的类。
3.4、java中为了保证类加载的安全,使用了双亲委派机制。
优先从启动类加载器中加载,这个称为父"。
父"无法加载到,再从扩展类加载器中加载,
这个称为“母"。双亲委派。如果都加载不到,
才会考虑从应用类加载器中加载。直到加载
到为止。
3.5、通过反射机制给属性赋值。
//反射属性Field
public class Student {
// Field翻译为字段,其实就是属性1成员
// 4个Field,分别采用了不同的访问控制权限修饰符
public int number;//Field对象
private String name;
protected int age;
boolean sex;
}
public class 通过反射机制获取访问对象的属性 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//使用反射机制,怎么访问一个对象的属性set get
String Student = null;
Class studentClass=Class.forName("reflect.Student");
Object obj= studentClass.newInstance();//底层调用无参数构造方法
//获取number属性(根据属性的名称来获取Field)
Field numberFiled=studentClass.getDeclaredField("number");
//给Obj(Student对象)的number属性赋值
/*虽然使用了反射机制,但是三要素还是缺一不可:
要素1 :obj对象
要素2 :number属性
要素3 :2222值
注意:反射机制让代码复杂了,但是为了一个“灵活”,这也是值得的
*/
numberFiled.set(obj,2222);//
System.out.println(numberFiled.get(obj));
//可以访问私有属性吗?不行
Field nameField=studentClass.getDeclaredField("name");//先通过属性的名字拿到属性
// 打破封装(反射机制的缺点:打破封装,可能会给不法分子留下机会! ! ! )
//这样设置完之后,在外部也是可以访问private的。
nameField.setAccessible(true);
//给name属性赋值
nameField.set(obj,"lisi");
System.out.println(nameField.get(obj));
}
}
3.6通过反射机制调用对象的方法
/*反射机制,让代码很具有通用性,可变化的内容都是写到配置文件当中,
将来修改配置文件之后,创建的对象不-样了,调用的方法也不同了,
但是java代码不需要做任何改动。这就是反射机制的魅力。*/
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;
}else{
return false;
}
}
public void login(int i){
}
//系统退出方法
public void logout(){
System.out.println("系统已经安全退出");
}
}
public class 通过反射机制调用对象的方法 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//不使用反射机制,怎么调用方法
//创建对象
UserService userService=new UserService();
//调用方法
boolean loginSuccess=userService.login("admin","123");
System.out.println(loginSuccess?"登录成功":"登录失败");
//使用反射机制来调用一个对象的方法
Class userServiceClass=Class.forName("reflect.UserService");
//创建对象
Object obj=userServiceClass.newInstance();
//获取method
Method loginMethod= userServiceClass.getDeclaredMethod("login", String.class, String.class);
// Method loginMethod1= userServiceClass.getDeclaredMethod("login", int.class);
//调用方法
//调用方法有几个要素?也需要4要素。
//反射机制中最最最最最重要的一个方法,必须记住。
/*四要素:
loginMethod方法
obj对象
"admin", "123” 实参
retValue返回值
*/
Object retValue=loginMethod.invoke(obj,"admin","123");
System.out.println(retValue);
}
}