一:基本概念
什么是反射
反射是java程序开发语言的特征之一,它允许java程序获取自身的信息,并且可以操作类或对象的内部属性。综合来说:对于一个类,我们知道它的属性和方法,对于一个对象,我们能够调用它的的属性和方法,这种动态获取信息以及动态调用方法的功能称为java的反射机制。
为什么需要反射,反射的作用
在java编译存在两种编译:静态编译,动态编译。静态编译:在编译时确定类型,动态编译在运行时确定类型,动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性。 Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时取得任何一个已知名称的class的内部信息。反射允许在运行时检查,修改程序的结构和行为,,java相关类型信息都在编译保存在class文件中,如果想在运行时该便,需要用到反射。简而言之:通过反射,我们可以获得程序或程序集中的每一个类型的成员和成员信息。腱反射的核心就是jvm在运行时动态加载类的或调用类的属性方法。
反射的基础:Class类
java程序在运行时保存所有的对象类型信息,而保存这些信息的就是class类。class类型封装了一个对象或者接口运行时的状态,当该类加载时,class类型的对象自动创建。
总的说:
class类也是类的一种,一个描述类的类,封装了描述的方法,属性等。
每一个类,java都为其保留了一个不变唯一的class对象,class类对象内容就是你创建对象的类的类型信息。比如创建一 个A类,java生成一个A类的class类对象。A类的对象都要通过class类对象实例化。
class类的对象只能由jvm创建。因为它没有公共构造函数。


二、反射的基本运用
如何使用反射?
首先获取到Class对象,其方式有三种
//(1)使用Class类的forName静态方法:
Class<?> class1 = Class.forName("java.lang.String");
//(2)直接获取某一个对象的class
Class<?> class2=String.class;
//(3)调用某个对象的getClass()方法
Class<? extends String> class3 = new String().getClass();
//Class对象唯一
System.out.println(class1.equals(class2)); //true
System.out.println(class3.equals(class2)); //true
1创建对象
通过反射创建对象的方式有两种
(1)直接利用newInstance创建,该方法必须调用的类必须有无参的构造器。
Object o = class1.newInstance();
String o1 = (String) class1.newInstance();
(2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用 指定的构造器构造类的实例。
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
2获取方法
三种主要方法
(1) 返回接口或类声明的所有方法,包含私有,公共,但不包含继承
public Method[] getDeclaredMethods() throws SecurityException
(2)返回某个类的所有公用(public)方法,包括其继承类的公用方法。
public Method[] getMethods() throws SecurityException
(3)返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象
public Method getMethod(String name, Class<?>... parameterTypes)
方法的调用
public class Son {
public void A(){
System.out.println("这是A方法");
}
public int B(int i){
return i+1;
}
public static void main(String[] args) throws Exception {
Son son = new Son();
Class<Son> sonClass = Son.class;
Method a = sonClass.getMethod("A");
a.invoke(son);
Method b = sonClass.getMethod("B", int.class);
Object invoke = b.invoke(son, 10);
System.out.println(invoke);
}
}
打印:
这是A方法
11
//打印出所有方法,参数,返回类型
Method[] methods = A.getDeclaredMethods();
for (Method method : methods) {
//依次获得方法的修饰符,返回类型和名称,外加方法中的参数
String methodString = Modifier.toString(method.getModifiers()) + " " ; //
private static
methodString += method.getReturnType().getSimpleName() + " "; // void
methodString += method.getName() + "("; // staticMethod
Class[] parameters = method.getParameterTypes();
Parameter[] p = method.getParameters();
for (Class parameter : parameters) {
methodString += parameter.getSimpleName() + " " ; // String
}
methodString += ")";
System.out.println(methodString);
3获取类的成员变量信息
两种主要方法
(1)获取类的所有公用(public)属性,包括其继承类的。
public Field getField(String name) throws NoSuchFieldException, SecurityException
(2)获取类声明的所有属性,包含私有,公共,但不包含继承
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException
public class Son {
private int i;
public String add;
public static void main(String[] args) throws Exception{
Class<Son> sonClass = Son.class;
Son son = new Son();
Field add1 = sonClass.getField("add");
add1.set(son,"111");
System.out.println(son);
Field i = sonClass.getDeclaredField("i");
i.set(son,12);
i.setAccessible(true);
System.out.println(son);
}
@Override
public String toString() {
return "Son{" +
"i=" + i +
", add='" + add + '\'' +
'}';
}
}
输出:
Son{i=0, add='111'}
Son{i=12, add='111'}
4创建数组
Class<?> cls = null;
try {
cls = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object array = Array.newInstance(cls,25);
//往数组里添加内容
Array.set(array,0,"hello");
Array.set(array,1,"Java");
Array.set(array,2,"fuck");
Array.set(array,3,"Scala");
Array.set(array,4,"Clojure");
//获取某一项的内容
System.out.println(Array.get(array,3));
本文深入解析Java反射机制,涵盖基本概念、动态获取类信息、创建对象、调用方法及成员变量,展示反射在运行时的强大功能。
408

被折叠的 条评论
为什么被折叠?



