为什么有
是什么
注意:
类加载就是程序执行时,加载Class文件的
类加载机制包括5个阶段:
图解类加载的加载阶段(太重要了,老铁,好好看)
如:实例化一个A类时
先将A类编译成A.class文件,放在主机硬盘上
当执行 A a = new A(),步骤在下面
步骤如下:对应上图序号
假如不通过new对象的方式,直接拿到A的class对象是不是就可以操作A对象的字段方法呢,答案是肯定的,这个就是反射
用上面的图翻译:
反射就是把将要访问类的各个部分映射成java.lang包下对应各个类
相关类 | 含义 |
---|---|
java.lang.Class | 该类映射将要访问的类 |
java.lang.reflect.Constructor | 该类映射将要访问的类中的构造方法 |
java.lang.reflect.Field | 该类映射将要访问的类中的属性 |
java.lang.reflect.Method | 该类映射将要访问的类中的方法 |
再写一次:Class对象对应某个类
1.Class.forName()静态方法
使用格式
Class c1 = Class.forName("java.lang.String");
说明:
2.对象的getClass方法
String s = "abc";
Class x = s.getClass();
说明
3.class属性
Class a = String.class
说明
Vip类
public class Vip {
int no;
String name;
//无参构造方法
public Vip(){}
//有参构造方法
public Vip(int no, String name) {
this.no = no;
this.name = name;
}
//重写toString()方法
@Override
public String toString() {
return "Vip{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
测试类
public static void main(String[] args) throws Exception {
//不使用反射机制创建对象
Vip v1 = new Vip();
Vip V2 = new Vip(110,"zhangsan");
//使用反射机制创建对象
Class c = Class.forName("com.thinkcoder.java.bean.Vip");
//调用无参构造
Object obj = c.newInstance();
System.out.println(obj);//Vip{no=0, name='null'}
//调用有参构造方法
//第一步:先获取构造方法
Constructor con = c.getDeclaredConstructor(int.class,String.class);
//第二步: 调用构造方法new对象
Object newObj = con.newInstance(111,"lisi");
System.out.println(newObj);//Vip{no=111, name='lisi'}
}
说明
Student类
public class Student {
//属性采用不同的访问修饰符
public int no;
private String name;
}
测试类
public static void main(String[] args) throws Exception {
//反射机制获取一个类
Class studentClass = Class.forName("com.thinkcoder.java.bean.Student");
Object obj = studentClass.newInstance();//obj代表Student对象
//获取公开属性no
Field noField = studentClass.getDeclaredField("no");
//给obj对象的name属性赋值
/*
* 给属性赋值三要素
* 1.obj对象
* 2.no属性
* 3.值为1
* */
noField.set(obj,1);
System.out.println(noField.get(obj));//1
//获取私有属性name
Field nameField = studentClass.getDeclaredField("name");
//打破封装,使私有属性可以访问
nameField.setAccessible(true);
nameField.set(obj,"zhangsan");
System.out.println(nameField.get(obj));//zhangsan
}
说明
com.thinkcoder.java.service.UserService类
public class UserService {
//实现简单登录验证
public boolean login(String name,String pwd){
if("admin".equals(name) && "123".equals(pwd)){
return true;
}
return false;
}
}
测试类
public static void main(String[] args) throws Exception {
//不使用反射机制调方法
//UserService userService = new UserService();
//userService.login("admin","123");
//使用反射机制调用方法
Class userService = Class.forName("com.thinkcoder.java.service.UserService");
//创建对象
Object obj = userService.newInstance();
//获取method
Method method = userService.getDeclaredMethod("login", String.class, String.class);
//调用方法用invoke
/*
* 要素1:对象obj
* 要素2:方法名method
* 要素3:实参列表"admin""123"
* 要素4:返回值retValue
* */
Object retValue= method.invoke(obj,"admin","123");
System.out.println(retValue);//true
}
说明
正如之上总结,java反射将类和其各个组成部分映射成各个对应的对象,通过对应的对象调用相关的属性方法
com.thinkcoder.java.service.UserService类
public class UserService {
//实现简单登录验证
public boolean login(String name,String pwd){
if("admin".equals(name) && "123".equals(pwd)){
return true;
}
return false;
}
}
classinfo1配置文件内容
className=com.thinkcoder.java.service.UserService
测试类
public class ResouceBundleTest {
public static void main(String[] args) {
//资源绑定器,只能绑定xxx.propertities文件,写路径时,扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("classinfo1");
String className = bundle.getString("className");
System.out.println(className);//com.thinkcoder.java.service.UserService
}
}
老铁当你获取了一个类的全限定类名之后,按照上边的操作,可以对该类各个组成部分进行操作
注意:
反射为什么叫反射呢?
就是将一个类和其组成部分映射(反射)到java.reflect包下对应的类
完结,反射的内容大致如此,以后看到源码部分时,或者学习反射更多相关东西,将补充