java反射学习
java反射机制的核心是在程序运行时动态的加载类并获取类的详细信息,从而操作类或对象的属性和方法。
java反射机制可以绕过java封装、直接调用私有属性的类或者方法
反射类的三种方法:
1、Class xxx = 类名.class,当表示类类型的时候Class需要大写
2、使用getClass()方法、需要已知该类的对象
3、使用forName(类的全称)方法、在使用forName方法时需要包含在try{}catch(){}异常处理中进行使用
public class Phone {
//属性
String screen = "qwer";
int cpu;
//方法
public void method01(){
System.out.println("第一个公有方法");
}
private void method02(){
System.out.println("第二个私有方法");
}
public static void main(String[] args) {
//获取类类型(Class对象)
//第一个表达式
Class c1 = Phone.class;
//第二个表达方式,已知该类的对象
Phone phone = new Phone();
Class c2 = phone.getClass();
//第三个表达式
//Class c3 = null;
try {
Class<?> c3 = Class.forName("Phone");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
如果直接使用forName()方法,会报一个未处理的错误、需要添加到try/catch异常处理中
public class Phone {
//属性
String screen = "qwer";
int cpu;
//方法
public void method01(){
System.out.println("第一个公有方法");
}
private void method02(){
System.out.println("第二个私有方法");
}
public static void main(String[] args) {
//第三个表达式
Class c3 = null;
c3 = Class.forName("Phone"); //在这里forName()会报错,需要写到异常处理方法内、参数为类的全称
}
}
在IDEA中我们可以选中forName()方法,然后使用Ctrl+Alt+T,选中try/catch
添加一个异常处理方法,就可以正常使用了。
实例化对象:
newinstance()实例化对象,它生成的对象只能反射无参的构造函数
Constructor.newinstance()可以反射所有构造函数,包括私有的
//实例化类的对象
//第一个表达式
try {
Phone.class.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//第二个表达式
try {
Class.forName("Phone").newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第三个表达式
try {
Phone.class.getConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
方法:
Method类,方法的对象,一个成员方法就是一个Method对象
getMethods()方法获取的是所有的public,包括父类继承的,不能获取私有方法
getDeclaredMethods()获取的是所有该类自己声明的方法,无视访问权限
invoke执行方法
如果这个方法是普通方法,那么第一个参数时类对象
如果这个方法是静态方法,那么第一个参数时类
//调用方法
try {
//获取方法
Method m1 = c2.getDeclaredMethod("method02");
//执行方法
try {
m1.invoke(c2.newInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
Method m2 = c2.getMethod("method01");
try {
m2.invoke(c2.newInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//获取类的属性(成员变量)的信息
//getFields()方法获取的是所有的Public的成员变量的信息
Field[] fs01 = c1.getFields();
for (Field field : fs01){
//成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//成员变量的名称
String fieldName = field.getName();
System.out.println(typeName+" "+fieldName);
}
//getDeclaredFields()获取的是该类所有声明的成员变量信息
Field[] fs02 = c1.getDeclaredFields();
for (Field field:fs02){
//得到成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName = field.getName();
System.out.println(typeName+" "+fieldName);
}
从结果可以看出,getFields()只能获取到类的公开的成员变量信息
getDeclaredFields()可以获取该类所有声明的成员变量信息
实例:
通过反射调用java.lang.runtime类,并执行系统命令。
一开始是这么写的,出现错误说是java.lang为私有属性、不可以访问。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
· 如何做好软件架构师
· 欧阳的2024年终总结,迷茫,重生与失业
· 史上最全的Cursor IDE教程
· 聊一聊 C#异步 任务延续的三种底层玩法
· 关于产品设计的思考
· 上位机能不能替代PLC呢?