反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。优点类似于黑客。(可以读和修改字节码文件)通过反射机制可以操作代码片段。(class文件)
反射机制的相关类在哪个包下?
java.lang.reflect.*
反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码,代表一个类型,代表整个类。
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)
Class c = Class.forName(“完整类名带包名”);
try {
Class c1 = Class.forName("java.lang.String"); //c1代表String类型
Class c2 = Class.forName("java.util.Date"); //c2代表Date类型
Class c3 = Class.forName("java.lang.Integer"); //c3代表Integer类型
Class c4 = Class.forName("java.lang.System"); //c4代表System类型
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class.forName()
- 静态方法
- 方法的参数是一个字符串
- 字符串需要的是一个完整类名
- 完整类名必须带有包名。java.lang包也不能省略
Class c = 对象.getClass();
public static void main(String[] args) {
Class c1 = null;
Class c2 = null;
Class c3 = null;
try {
c1 = Class.forName("java.lang.String");
c2 = Class.forName("java.util.Date");
c3 = Class.forName("java.lang.Integer");
Class c4 = Class.forName("java.lang.System");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String str = "abcd"; //字符串对象
Class aClass = str.getClass(); //aClass代表String.class的字节码文件,aClass代表Stirng类型·
System.out.println(aClass == c1); //true(==判断的是对象的内存地址)
Date date = new Date();
Class cdate = date.getClass();
System.out.println(cdate == c2); //true(cdate和c2两个变量中保存的内存地址都是一样的,都指向方法区中的字节码文件)
}
Class c = 任何类型.class;
public static void main(String[] args) {
Class c1 = null;
Class c2 = null;
Class c3 = null;
try {
c1 = Class.forName("java.lang.String");
c2 = Class.forName("java.util.Date");
c3 = Class.forName("java.lang.Integer");
Class c4 = Class.forName("java.lang.System");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Java语言中任何一种类型,包括基本数据类型,它都有.class属性
Class stringClass = String.class; //stringClass代表Stirng类型
Class dateClass = Date.class; //dateClass代表Date类型
System.out.println(stringClass == c1);
System.out.println(dateClass == c2);
}
public class Main {
public static void main(String[] args) {
try {
//通过反射机制,获取Class,通过Class来实例化对象
Class aClass = Class.forName("com.dong.Person");
Object o = aClass.newInstance();
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
//Person类
class Person {
}
成功创建对象
newInstance()这个方法会调用Person这个类的无参构造方法,完成对象的创建。
class Person {
public Person() {
System.out.println("运行无参构造方法");
}
}
如果定义了有参构造方法但没有无参构造方法就会报错
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
所以,一般最好带上无参构造方法
Student类
public class Student {
private String name;
protected int age;
boolean sex;
public int no;
public static final double MATH_PI = 3.1415926;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class student = Class.forName("com.dong.Student");
Object o = student.newInstance(); //o就是Student对象(底层调用无参数构造方法)
//获取no属性(根据属性的名称来获取Field)
Field no = student.getDeclaredField("no");
no.set(o,123); //给obj对象的no属性赋值123
System.out.println(no.get(o));
}
获取私有属性
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class student = Class.forName("com.dong.Student");
Object o = student.newInstance(); //o就是Student对象(底层调用无参数构造方法)
//获取私有的name
Field name = student.getDeclaredField("name");
//给name属性赋值
name.set(o,"皮皮虾");
System.out.println(name.get(o));
}
访问报错
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class student = Class.forName("com.dong.Student");
Object o = student.newInstance(); //o就是Student对象(底层调用无参数构造方法)
//获取私有的name
Field name = student.getDeclaredField("name");
//打破封装
name.setAccessible(true);
//给name属性赋值
name.set(o,"皮皮虾");
System.out.println(name.get(o));
}
setAccessible(true)这样设置后,在外部也可以访问private
反射机制缺点:打破封装可能会给不法分子留下机会!!!
User类
public class User {
int no;
int age;
/**
* 登陆方法
*/
public boolean login(String name,String password) {
if ("admin".equals(name) && "123".equals(password)) {
return true;
}
return false;
}
/**
* 退出
*/
public void logout() {
System.out.println("系统已经安全退出");
}
}
测试
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class aClass = Class.forName("com.dong.User");
//创建对象
Object obj = aClass.newInstance();
//获取Method
Method login = aClass.getDeclaredMethod("login", String.class, String.class);
Object admin = login.invoke(obj, "admin", "123");
System.out.println(admin);
Method logout = aClass.getDeclaredMethod("logout");
logout.invoke(obj);
}
}
getDeclaredMethod():参数1:指明获取的方法的名称,参数2:指明获取的方法的形参列表
invoke():参数1:方法的调用者,参数2:给方法形参赋值的实参
反射机制,让代码很具有通用性,可变化的内容都是写到配置文件中,将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是java代码不需要任何改动。这就是发射机制能力。
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class aClass = Class.forName("com.dong.User");
Constructor declaredConstructor = aClass.getDeclaredConstructor(int.class, int.class);
Object o = declaredConstructor.newInstance(1, 2);
System.out.println(o);
}
}
getDeclaredConstructor():参数:指明构造器的参数列表
创作不易,如果帮到大家的话,可以点赞关注和收藏哦,谢谢各位!
博主更多博文