反射的概念及演示
1).什么是“反射”:它是Java提供的一种技术,这种技术可以让我们任意的加载某个类,并创建它的对象,甚至不用知道这个类的名字、以及内部结构。
2).“反射”的作用:可以解开“类与类之间的耦合关系”。
运行时class文件的加载
1).当我们的程序第一次创建某个类的对象时,会去找它的class文件;如果在本次运行过程中,再创建此类对象,就不会再去找class文件了。
注意:JVM在运行时,为任何的类,都会在“方法区”中创建它的Class对象,而且每个类,只创建一个”Class对象”。
获取Class对象的三种方式
1).getClass()方法
2).类名.class
3).Class.forName(“全类名”);【常用】
示例代码:
public static void main(String[] args) throws ClassNotFoundException {
//1.getClass()方法获取此类的Class对象
Student stu1 = new Student();//创建Class对象
Class c1 = stu1.getClass();
//2.类名.class
Class c2 = Student.class;//如果没有Class,会创建Class对象;如果有,就直接获取
//3.Class.forName("全类名-带包名的类名");【常用】
Class c3 = Class.forName("com.itheima.demo03_获取Class对象的三种方式.Student");//没有Class则创建,有则直接返回
System.out.println(c1 == c2);//true
System.out.println(c1 == c3);//true
}
获取构造方法并创建对象-Constructor
在Class类中,有四个方法,可以获取一个类的构造方法:
A).批量获取:【了解】
1). public Constructor[] getConstructors():获取所有的“公有”构造方法。
2). public Constructor[] getDeclaredConstructors():获取所有的构造方法,包括:公有、受保护、默认、私有。
B).单个获取:【掌握】
3). public Constructor getConstructor(Class<?>… parameterTypes):获取某个“公有”的构造方法。
4).public Constructor getDeclaredConstructor(Class<?> … parameterTypes):获取某个构造方法,可以是任何的访问权限修饰符。
创建对象:
Constructor类–> newInstance()
注意:如果没有访问权限,需要设置暴力访问:Constructor类 --> setAccessble(true)
综合示例代码:
public class Student {
public Student(float f) {
System.out.println("公有的、float参数的构造方法...");
}
public Student(){
System.out.println("调用了公有、无参的构造方法...");
}
protected Student(int a){
System.out.println("调用了受保护的、int参数的构造方法...");
}
Student(long a){
System.out.println("调用了默认的、long参数的构造方法...");
}
private Student(String s,int a){
System.out.println("调用了私有的、String,int参数的构造方法...");
}
}
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Student的Class对象
Class stuClass = Class.forName("com.itheima.demo04_获取构造方法并创建对象_Constructor.Student");
//2.获取它内部的Student的构造方法
System.out.println("获取所有公有构造方法:");
Constructor[] cs = stuClass.getConstructors();
System.out.println("数组长度:" + cs.length);
for (int i = 0; i < cs.length; i++) {
System.out.println(cs[i]);
}
System.out.println("获取所有构造方法,包括:公有、受保护、默认、私有:");
Constructor[] cs2 = stuClass.getDeclaredConstructors();
for (int i = 0; i < cs2.length; i++) {
System.out.println(cs2[i]);
}
System.out.println("获取公有、无参构造方法:");
Constructor ct1 = stuClass.getConstructor();
System.out.println(ct1);
System.out.println("获取公有、有参构造方法:");
Constructor ct2 = stuClass.getConstructor(float.class);
System.out.println(ct2);
System.out.println("调用构造方法,创建对象:");
Object obj1 = ct1.newInstance();//调用了公有、无参构造方法,创建了一个Student对象
System.out.println("调用构造方法,创建对象:");
Object obj2 = ct2.newInstance(1.72F);//由于要调用带参的构造方法,必须要传递实参
System.out.println("获取私有构造方法:");
Constructor ct3 = stuClass.getDeclaredConstructor(String.class, int.class);
ct3.setAccessible(true);//设置:暴力访问
Object obj3 = ct3.newInstance("张三", 20);
}
}
正常示例代码:
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取它的Class
Class stuClass = Class.forName("com.itheima.demo04_获取构造方法并创建对象_Constructor.Student");
//2.获取它的私有构造方法
Constructor ct1 = stuClass.getDeclaredConstructor(String.class, int.class);
//3.设置暴力访问
ct1.setAccessible(true);
//4.调用此构造方法,创建对象
Object obj1 = ct1.newInstance("张三", 20);
}
}
获取成员属性并赋值和取值-Field
A).批量获取:【了解】
1).public Field[] getFields():获取所有“公有”成员属性。
2).public Field[] getDeclaredFields():获取所有成员属性,包括:公有、受保护、默认、私有。
B).单个获取:
3).public Field getField(String fieldName):获取某个“公有”成员属性。
4).public Field getDeclaredField(String fieldName):获取某个成员属性,可以是公有、受保护、默认、私有。
为成员属性赋值:
Field类 --> set(Object 目标对象,Object 值)
示例代码:
public class Student {
public String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Class
Class stuClass = Class.forName("com.itheima.demo05_获取成员属性并赋值和取值_Field.Student");
System.out.println("获取公有name属性:");
Field nameField = stuClass.getField("name");
System.out.println(nameField);
System.out.println("獲取私有的age属性:");
Field ageField = stuClass.getDeclaredField("age");
ageField.setAccessible(true);//设置:暴力访问
System.out.println(ageField);
//要操作两个属性,必须先创建对象
Object obj1 = stuClass.getConstructor().newInstance();
Object obj2 = stuClass.getConstructor().newInstance();
System.out.println(obj1);
System.out.println(obj2);
//为第一个对象的属性赋值为:刘德华,18
//以前:对象.属性 = 值;
//反射:属性Field对象.set(目标对象,值)
nameField.set(obj1, "刘德华");
ageField.set(obj1, 18);
//为第二个对象的属性赋值为:成龙,30
nameField.set(obj2, "成龙");
ageField.set(obj2, 30);
System.out.println(obj1);
System.out.println(obj2);
}
}
获取成员方法并调用-method
A).批量获取:【了解】
1).public Method[] getMethods():获取所有“公有”成员方法。
2).public Method[] getDeclaredMethods():获取所有成员方法,包括:公有、受保护、默认、私有。
B).单个获取:
3).public Method getMethod(String methodName,Class … paramtTypes):获取某个“公有”成员方法。
4).public Method getDeclaredMethod(String methodName,Class … parametTypes):获取某个成员方法,可以是公有、受保护、默认、私有。
调用方法:
Method类 --> invoke(Object 目标对象,Object … 实参列表)
注意:如果没有访问权限,要设置暴力访问:Method类的–> setAccessible(true)
示例代码:
public class Student {
public void show1(){
System.out.println("调用了公有的show1()...");
}
private int show2(String name){
System.out.println("调用了私有的show2(),参数name = " + name);
return 120;
}
}
public class Demo06 {
public static void main(String[] args) throws Exception {
//1.获取Class
Class stuClass = Class.forName("com.itheima.demo06_获取成员方法并调用_method.Student");
System.out.println("获取公有的show1()");
Method show1Method = stuClass.getMethod("show1");
//有访问权限的,也可以设置暴力访问,但没有必要。
System.out.println(show1Method);
System.out.println("获取私有的show2():");
Method show2Method = stuClass.getDeclaredMethod("show2", String.class);
show2Method.setAccessible(true);//设置暴力访问
System.out.println(show2Method);
//2.要调用方法,必须先创建对象
Object obj = stuClass.getConstructor().newInstance();
//3.调用show1
show1Method.invoke(obj);//invoke()内部会去调用show1()
//4.调用show2
Object result = show2Method.invoke(obj, "刘德华");//invoke()内部会去调用show2()
System.out.println("返回值:" + result);
}
}
反射练习
实现步骤:
1).创建一个配置文件:demo01.txt;
2).写测试类:反射加载配置文件中配置的类;
3).编写一个Student类,并配置到配置文件中。
4).运行测试类,反射加载Student类,并创建对象,调用方法。
配置文件内容:
className = com.itheima.Student
methodName = study
实现代码:
public class Student {
public void study(){
System.out.println("我在学习Java,我的目标是月薪过万!");
}
}
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Class对象
String className = getValue("className");//String className = "com.itheima.demo07_反射练习.Student"
Class aClass = Class.forName(className);//forName("com.itheima.demo07_反射练习.Student")
//2.获取方法对象
Method methodName = aClass.getDeclaredMethod(getValue("methodName"));
//3.要调用方法,先创建对象
Object obj = aClass.getConstructor().newInstance();
//4.调用方法[无参,无返回值]
methodName.invoke(obj);
}
public static String getValue(String key) {
Properties pro = new Properties();
try (FileReader in = new FileReader("demo01.txt")) {
pro.load(in);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return pro.getProperty(key);
}
}
来源:CSDN
作者:樂少
链接:https://blog.csdn.net/weixin_43473420/article/details/104212620