反射
定义
java核心技术卷1中的定义:能够分析类能力的程序称为反射。
反射:将类的各个部分封装为其它对象,这就是反射机制。
百度:反射就是根据给出的类名(字符串)来生成对象
-
好处:
- 1.在程序运行时期操纵对象。
Idea程序在运行期间,当你定义一个Integer的对象a,a.就会展示所有的方法名
Integer类在Idea运行期间就被ClassLoader加载到内存中,当点击.时只需及那个Method数组中的名字显示出来就可以了。
-
2.降低程序耦合性。
举例:加载数据库驱动
编译期报错
Class.forName("com.mysql.jdbc.Driver");//加载数据库驱动
直接报错
new com.mysql.jdbc.Driver()//创建driver对象,加载数据库驱动
获取Class类对象的方式
class.forName("全限定类名")
类名.class
-
实例.getClass()
Class类的方法:
关于Field
返回类型 方法名 描述 Field[]
getFields()
获取公有成员变量
Field
getField(String name)
通过公有变量名获取公有对象
Field[]
getDeclaredFields()
获取全部变量
Field
getDeclaredField(String name)
通过变量名获取变量
关于Constructor
返回类型 方法名 Constructor[]
getConstructors()
Constructor
getConstructor(类... parameterTypes)
Constructor[]
getDeclaredConstructors()
Constructor
getDeclaredConstructor(类... parameterTypes)
关于Methond
返回类型 方法名 Methond[]
getMethods()
Methond
getMethod(String name, 类<?>... parameterTypes)
Methond[]
getDeclaredMethods()
Methond
getDeclaredMethod(String name, 类<?>... parameterTypes)
如果是私有构造器:
constructor.setAccessible(true);
成员变量相关:
反射的应用场景:框架的底层
在用框架的时候我们将需要配置的东西写在配置文件中,将对象创建的主动权交出去。(控制反转Ioc)
IoC中最基本的Java技术就是“反射”编程。通俗的说,反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让应用在运行时才动态决定生成哪一种对象。反射的应用是很广泛的,像Hibernate、Spring中都是用“反射”做为最基本的技术手段。
通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。
简单模拟:实现一个类可以在运行时动态创建任意对象,并且执行任意方法。
Person类:
package com.zyb.pric;
public class Person {
public int id;
private String name;
public Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
System.out.println("getId被执行");
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package com.zyb.pric;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//1.加载配置文件
Properties pro = new Properties();
ClassLoader classLoader = ReflectDemo.class.getClassLoader();
InputStream p = classLoader.getResourceAsStream("pro.properties");
pro.load(p);
//2.获取文件中的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cl = Class.forName(className);
//4.创建对象
Object obj = cl.newInstance();
Field declaredField = cl.getDeclaredField("id");
declaredField.set(obj,545);
//5.获取方法对象
Method method = cl.getMethod(methodName);
//执行方法
Object invoke = method.invoke(obj);
System.out.println(invoke);
}
}
pro.properties
className=com.zyb.pric.Person
methodName=getId
读取类中的所有相关信息:
package com.zyb.pric;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
public class ReflectionTest {
public static void main(String[] args) {
//read class name from command line args or user input
String name;
if(args.length>0){
name=args[0];
}else{
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date):");
name=in.next();
}
try{
//print class name and superclass name (if!=Object)
Class cl=Class.forName(name);
Class supercl=cl.getSuperclass();
String modifiers= Modifier.toString(cl.getModifiers());
System.out.print(" class "+name);
if(supercl!=null&&supercl!=Object.class) System.out.print(" extends "
+supercl.getName());
System.out.print("\n{\n");
printConstructors(cl);
System.out.println();
printMethods(cl);
System.out.println();
printFields(cl);
System.out.println("}");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
System.exit(0);
}
/**
* Prints all constructors of a class
* @param cl a class
*/
public static void printConstructors(Class cl){
Constructor[] constructors = cl.getDeclaredConstructors();
for (Constructor c: constructors) {
String name=c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(name+"(");
//print parameter types
Class[]paramTypes = c.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if(i>0) System.out.print(", ");
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
/**
* Prints all methods of a class
* @param cl a class
*/
public static void printMethods(Class cl){
Method[] methods = cl.getDeclaredMethods();
for (Method m:methods){
Class resType = m.getReturnType();
String name=m.getName();
System.out.print(" ");
//print modifiers,return type and method name
String modifiers= Modifier.toString(m.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(resType.getName()+" "+name+"(");
//print parameter types
Class[] paramTypes = m.getParameterTypes();
for (int i = 0; i <paramTypes.length ; i++) {
if(i>0) System.out.print(", ");
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
/**
* Prints all fields of a class
* @param cl a class
*/
public static void printFields(Class cl){
Field[] fields = cl.getDeclaredFields();
for (Field f: fields) {
Class<?> type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+name+";");
}
}
}
输入java.lang.Double的运行结果: