关于反射
getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
顺便记一下:
@Override
这个标签
可以当作注释用,没什么特别的
可以告诉读你代码的人,这是对它父类方法的重写,其实很多代码规范没有为什么,规范就是规范,代码的可读性还是很重要的。
编译器可以给你验证
@Override
下面的方法名称是否是你父类中所有的,如果没有就会报错。
比如当你想要在子类中重写父类的一个方法,但是你把名字打错了,当你写了@Override编译器会提示你,你写的这个方法父类中没有;但是如果你没有写@Override编译器就会觉得这个是你子类中写的新的方法,并不会报错,到时候你debug还是很麻烦的一件事。
摘自【https://blog.csdn.net/upc1607020107/article/details/81274398】感觉这个博主说的就很好了,就直接摘抄过来了
反射的其他两种
String str = "test";
System.out.println(str.getClass());
//静态方法
Class class_name = Class.forName("java.lang.String");
getDeclaredField()
:获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
Class类提供了以下几个方法来获取Method
Method getMethod(name, Class...)
:获取某个public的Method(包括父类)Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method(不包括父类)Method[] getMethods()
:获取所有public的Method(包括父类)Method[] getDeclaredMethods()
:获取当前类的所有Method(不包括父类)
需要执行的话,就需要将方法名传入invoke()方法。有以下两种方式
System.out.println(substring.invoke(test));
//调用带参数的方法,需要传参
System.out.println(substring.invoke(test,"admin"));
执行命令的方法
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc");
关于Final 修饰符,它可以用来修饰类,方法,变量
- 修饰类:当一个类使用final修饰时,表明这个类不能被继承。
- 修饰方法,表明这个方法被锁定,任何继承这个类之后都不能修改这个方法的含义。
- 修饰变量,这个使用的是最多的,也是了解final修饰符的主要原因之一,主要记住一点就是使用final修饰的变量,再初始化之后就不能被修改。
Class.forName(className)
相当于Class.forName(className, true, currentLoader
第⼆个参数表示是否初始化,在forName
的时候,构造函数并不会执⾏,而是执⾏类初始化。他会执行static{}
静态块里面的内容
package com.test;
import java.io.IOException;
public class web {
public static void main(String[] args) throws Exception {
Class.forName("com.test.Calc");
}
}
class Calc{
static {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}
反射原理
反射就是对于任意一个类,可以知道它的所有属性和方法,对于任意一个对象都能调用它的任意一个方法,在运行状态中,动态调用方法的功能获取对象的三种方式
- Class.forName()
Class aClass = Class.forName("com.reflecttest.Person");
System.out.println(aClass);
- 类名.class
Class personClass = Person.class;
System.out.println(personClass);
- 对象.getClass()
Person person = new Person();
Class aClass1 = person.getClass();
System.out.println(aClass1);
获取对象的功能的13种常用方法
package com.reflecttest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo1 {
public static void main(String[] args) throws Exception {
/*
* 反射就是对于任意一个类,可以知道它的所有属性和方法,对于任意一个对象都能调用它的任意一个方法
* 在运行状态中,动态调用方法的功能
*获取对象的三种方法
* 1. Class.forName()
* 2. 类名.class
* 3. getClass()
* */
Class aClass = Class.forName("com.reflecttest.Person");
System.out.println(aClass);
System.out.println("===========================");
Class personClass = Person.class;
System.out.println(personClass);
System.out.println("===========================");
Person person = new Person();
Class aClass1 = person.getClass();
System.out.println(aClass1);
/*
* 1. 获取对象的功能
* 1.1 获取成员变量
* */
//获取所有的public变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
//获取指定的public变量
Field field = personClass.getField("name");
System.out.println(field);
//获取所有成员变量(包括private & protected)
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取指定的私有成员变量
Field age = personClass.getDeclaredField("age");
System.out.println(age);
System.out.println("============================================");
/*1.2 获取构造方法
*/
Constructor[] constructors = personClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获取指定方法(有参无参)
Constructor constructor = personClass.getConstructor(String.class, int.class, String.class);
System.out.println(constructor);
System.out.println("==========================");
Constructor[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//1.3 获取成员方法
// 获取所有公有成员方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取指定成员方法
Method method = personClass.getMethod("love");
System.out.println(method);
//操作
method.invoke(person);
System.out.println("========================================");
//获取所有成员方法
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
Method love = personClass.getDeclaredMethod("love");
love.invoke(person);
}
}
访问并修改调用私有属性的时候,出于安全性检查,会拒绝调用,这时可以使用一行代码来忽略这个私有属性的访问权限安全性检测。
反射练习案例
在不修改代码的情况下,创建任意类和执行任意方法
这里主要是涉及到一个配置文件的使用,这里如果是在maven中,参考https://www.yuque.com/m0re/demosec/sr2n6h#PkCid
package com.reflecttest;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//创建Properties对象
Properties properties = new Properties();
//加载配置文件,转换为一个集合(使用到加载器)
// 获取class目录下的配置文件
ClassLoader classLoader = ReflectDemo2.class.getClassLoader();//获取同文件的加载器
InputStream is = classLoader.getResourceAsStream("pro.properties");//转换为流
properties.load(is);//载入
//获取配置文件中定义的数据
String className = properties.getProperty("ClassName");
String methodName = properties.getProperty("MethodName");
//加载该类进内存
Class aClass = Class.forName(className);
//创建对象
Object obj = aClass.newInstance();
//获取方法对象
Method method = aClass.getMethod(methodName);
method.invoke(obj);
}
}