目录
一、概述
1、框架
2、反射
好处:
二、获取字节码class对象的方法
1、第一阶段——Source源代码阶段
2、第二阶段——Class类对象阶段
3、第三阶段——Runtime运行时阶段
4、代码演示
结论:
三、Class对象功能概述
1、获取成员变量
Field[] getFields()(获取所有公共成员变量)
Field getField(String name)(获取指定公共成员变量)
Field[] getDeclaredFields()(获取所有成员变量)
Field getDeclaredField(String name)(获取指定成员变量)
代码演示:
2、获取构造方法
Constructor[] getConstructors()(获取所有公共构造方法)
Constructor getConstructor(Class... parameterTypes)(获取所有指定公共构造方法)
Constructor[] getDeclaredConstructors()(获取所有构造方法)
Constructor getDeclaredConstructor(Class... parameterTypes)(获取指定构造方法)
代码演示:
3、获取成员方法
Method[] getMethods()(获取所有公共方法,包括继承自Object的)
Method getMethod(String name, Class... parameterTypes)(获取所有指定公共方法)
Method[] getDeclaredMethods()(获取所有方法,不包括继承自Object的)
Method getDeclaredMethod(String name, Class... parameterTypes)(获取指定方法)
代码演示:
4、获取类名
String getName()
代码演示:
四、案例
1、需求
2、实现分析
3、实现步骤
4、代码演示
学生类:
测试类:
一、概述
反射——框架设计的灵魂
1、框架
①半成品软件;
②可以在框架的基础上进行软件开发,简化代码;
③使用框架不需要会反射,但自己要开发框架就需要会反射;
2、反射
将类的各个组成部分封装为其他对象,这就是反射机制;
好处:
①可以在程序运行的过程中操作这些对象;
②可以解耦,提高程序的可扩展性;
二、获取字节码class对象的方法
1、第一阶段——Source源代码阶段
Class.forName("全类名"):将字节码文件加载到内存,返回Class对象;
多用于配置文件,将类名定义在配置文件中。读取文件,加载类;
2、第二阶段——Class类对象阶段
类名.class:通过类名的属性class获取;
多用于参数的传递;
3、第三阶段——Runtime运行时阶段
对象.getClass():getClass()定义在Object类中;
多用于对象获取字节码的方式;
4、代码演示
package study.reflect;
import study.method_references.Person;
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException {
//1、第一阶段——Source源代码阶段
//Class.forName("全类名"):将字节码文件加载到内存,返回Class对象;
Class c1 = Class.forName("study.method_references.Person");
System.out.println(c1);
//2、第二阶段——Class类对象阶段
//类名.class:通过类名的属性class获取;
Class c2 = Person.class;
System.out.println(c2);
//3、第三阶段——Runtime运行时阶段
//对象.getClass():getClass()定义在Object类中;
Person person = new Person();
Class c3 = person.getClass();
System.out.println(c3);
//这三个class都是同一个
System.out.println(c1==c2);
System.out.println(c1==c3);
//true
//true
}
}
结论:
同一字节码(*.class)文件在程序执行的过程中只会被执行一次,无论通过哪种方式获取的class对象都是同一个;
三、Class对象功能概述
别忘了,先获取类,再通过类获取;
1、获取成员变量
Field[] getFields()(获取所有公共成员变量)
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共(public修饰的)字段;
Field getField(String name)(获取指定公共成员变量)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共(public修饰的)成员字段;
Field[] getDeclaredFields()(获取所有成员变量)
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段;
Field getDeclaredField(String name)(获取指定成员变量)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段;
代码演示:
package study.reflect;
import study.method_references.Person;
import java.lang.reflect.Field;
public class GetFieldTest {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//1、获取所有公共成员变量
Person person = new Person();
Class c = person.getClass();
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
//public java.lang.String study.method_references.Person.name
}
//2、获取指定公共成员变量
Field field = c.getField("name");
System.out.println(field);
//public java.lang.String study.method_references.Person.name
//3、获取指定的成员变量(不关乎修饰符)
Field field1 = c.getDeclaredField("name");
System.out.println(field1);
//public java.lang.String study.method_references.Person.name
Field field2 = c.getDeclaredField("name1");
System.out.println(field2);
//private java.lang.String study.method_references.Person.name1
//4、获取所有成员变量(不关乎修饰符)
Field[] fields1 = c.getDeclaredFields();
for (Field field11 : fields1) {
System.out.println(field11);
//private java.lang.String study.method_references.Person.name1
//public java.lang.String study.method_references.Person.name
}
//5、对获取的变量进行操作
//获取值
Person p1 = new Person();
Object value1 = field.get(p1);
System.out.println(value1);
//设置值
field.set(p1,"大哥");
Object value2 = field.get(p1);
System.out.println(value2);//大哥
}
}
2、获取构造方法
Constructor<?>[] getConstructors()(获取所有公共构造方法)
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共(public修饰的)构造方法;
Constructor<T> getConstructor(Class<?>... parameterTypes)(获取所有指定公共构造方法)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共(public修饰的)构造方法;
Constructor<?>[] getDeclaredConstructors()(获取所有构造方法)
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法;
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)(获取指定构造方法)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法;
代码演示:
package study.reflect;
import study.method_references.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class GetConstructorsTest {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//0、获取类
Person person = new Person();
Class c = person.getClass();
//1、获取所有公共构造方法
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
//public study.method_references.Person(java.lang.String)
//public study.method_references.Person()
}
//2、获取所有指定公共构造方法
Constructor constructor = c.getConstructor(String.class);
System.out.println(constructor);
//public study.method_references.Person(java.lang.String)
//3、获取所有构造方法
Constructor[] constructors1 = c.getDeclaredConstructors();
for (Constructor constructor1 : constructors1) {
System.out.println(constructor1);
//private study.method_references.Person(java.lang.String,java.lang.String)
//public study.method_references.Person(java.lang.String)
//public study.method_references.Person()
}
//4、获取指定构造方法
Constructor constructor1 = c.getDeclaredConstructor(String.class,String.class);
System.out.println(constructor1);
//private study.method_references.Person(java.lang.String,java.lang.String)
//5、使用构造方法创建对象
Object p1 = constructor.newInstance("大哥");
Person p2 = (Person)p1;
System.out.println(p2.getName());//大哥
p2.setName("大哥pro");
System.out.println(p2.getName());//大哥pro
}
}
3、获取成员方法
Method[] getMethods()(获取所有公共方法,包括继承自Object的)
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共(public修饰的) member 方法;
Method getMethod(String name, Class<?>... parameterTypes)(获取所有指定公共方法)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共(public修饰的)成员方法;
Method[] getDeclaredMethods()(获取所有方法,不包括继承自Object的)
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;
Method getDeclaredMethod(String name, Class<?>... parameterTypes)(获取指定方法)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法;
代码演示:
package study.reflect;
import study.method_references.Person;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class getMethodsTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//0、获取类
Person person = new Person();
Class c = person.getClass();
//1、获取所有公共方法
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
//public java.lang.String study.method_references.Person.getName()
//public void study.method_references.Person.setName(java.lang.String)
//public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
//public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
//public final void java.lang.Object.wait() throws java.lang.InterruptedException
//public boolean java.lang.Object.equals(java.lang.Object)
//public java.lang.String java.lang.Object.toString()
//public native int java.lang.Object.hashCode()
//public final native java.lang.Class java.lang.Object.getClass()
//public final native void java.lang.Object.notify()
//public final native void java.lang.Object.notifyAll()
}
//2、获取所有指定公共方法
Method method = c.getMethod("getName");
System.out.println(method);
//public java.lang.String study.method_references.Person.getName()
System.out.println("===============================");
//3、获取所有方法
Method[] methods1 = c.getDeclaredMethods();
for (Method method1 : methods1) {
System.out.println(method1);
//public java.lang.String study.method_references.Person.getName()
//public void study.method_references.Person.setName(java.lang.String)
//private java.lang.String study.method_references.Person.getName1()
//private void study.method_references.Person.setName1(java.lang.String)
}
//4、获取指定方法
Method method1 = c.getDeclaredMethod("getName1");
System.out.println(method1);
//private java.lang.String study.method_references.Person.getName1()
//5、调用方法
Person p = new Person();
//私有方法,可采用暴力反射
method1.setAccessible(true);
method1.invoke(p);//getName1被执行了……
}
}
4、获取类名
String getName()
以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称;
代码演示:
package study.reflect;
import study.method_references.Person;
public class getNameTest {
public static void main(String[] args) {
//0、获取类
Person person = new Person();
Class c = person.getClass();
//1、获取类名
String className = c.getName();
System.out.println(className);//study.method_references.Person
}
}
四、案例
1、需求
写一个“框架”,在不改变类的代码的情况下,可以创建任意类,并调用其中的任意方法;
2、实现分析
配置文件+反射;
3、实现步骤
①将需要创建对象的全类名和需要执行的方法定义在配置文件中;
②在程序中加载配置文件;
③使用反射技术来加载类文件进内存;
④创建对象;
⑤执行方法;
4、代码演示
学生类:
package study.reflect;
public class Student {
public void study(){
System.out.println("学习啦……");
}
public void sleep(){
System.out.println("睡觉啦……");
}
}
测试类:
package study.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class DemoTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//①将需要创建对象的全类名和需要执行的方法定义在配置文件中;
//②在程序中加载配置文件;
//创建Properties
Properties properties = new Properties();
//获取类加载器
ClassLoader classLoader = DemoTest.class.getClassLoader();
//使用类加载器读取配置文件
InputStream inputStream = classLoader.getResourceAsStream("pro.properties");
//将配置文件转换为一个Properties集合
properties.load(inputStream);
//③使用反射技术来加载类文件进内存;
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
Class c = Class.forName(className);
//④创建对象;
Object o = c.getDeclaredConstructor().newInstance();
//⑤执行方法;
Method method = c.getMethod(methodName);
method.invoke(o);
//睡觉啦……
}
}
标签:lang,反射,Java,String,Class,Person,详解,java,public From: https://blog.51cto.com/u_13272819/7956123