java反射机制

反射是什么

指程序可以访问、检测和修改它本身状态或行为的一种能力,反射就是用来让开发者知道这个类中有什么成员,以及别的类中有什么成员

反射机制提供了下面这些功能:

  1. 在运行的时候判断任意一个对象所属的类
  2. 在运行时构造一个类的对象
  3. 在运行时判断一个类所具有的变量和方法
  4. 在运行时调用任意一个对象的方法

现在很多出名的框架都用到了反射机制,比如spring。这里附上Reflection API

http://www.51gjie.com/java/780.html

获取Class对象

Class类其实也是类的一种,表示运行时的相关信息,Class类只有一个私有的构造函数,只能有JVM能创建Class的实例,所以不能直接new一个,通常有以下3种方法获取:

  1. forName静态方法

     Class<?> c1 = Class.forName("java.lang.Integer");
    其中类的名称要写类的完整路径
  2. getClass()方法

     Integer i1 = 1;
    Class<?> c2 = i1.getClass();
    如果我们有一个类的对象,那么我们可以通过 Object.getClass 方法获得该类的 Class 对象。
  3. 直接获取class

    Class<?> c3 = Integer.class;
    若我们知道要获取的类类型的名称时,我们可以使用 class 语法获取该类类型的对象

获取Class类的方法,属性,构造函数

Field

Field提供了类所有的属性的信息,以及动态访问。可以通过Class提供的方法获取:

image.png

实例:

package test2; 

import java.lang.reflect.Field;

public class fan1 {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = fan2.class;
Field[] fields = clazz.getDeclaredFields();
try {
Field fields2 = clazz.getDeclaredField("name");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Field a:fields) {
System.out.println(a);
}
}
}
class fan2 {
private String name;
public int age;
public fan2(String name,int age) {
this.name = name;
this.age = age;
}
}

output:
private java.lang.String test2.fan2.name

public int test2.fan2.agefield可以获取到Class下的所有属性。

修改属性:

package test2;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class fan3 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
fan4 test = new fan4("test",11);
Field fields4 = test.getClass().getDeclaredField("age");
fields4.setAccessible(true);
try {
fields4.set(test, 100);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("now age is "+test.age );

`}`

}
class fan4 {
private String name;
public int age;
public fan4(String name,int age) {
this.name = name;
this.age = age;
System.out.println("there is 2 parame and age is "+age);
}
public  fan4() {
System.out.println("there is no parame");
}
private void echo(String id) {
System.out.println("my id is "+id);
}
}

output:
there is 2 parame and age is 11
now age is 100
Method

Method可以查看所有的方法,以及动态访问。

image.png

实例:

 package test2;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class fan1 {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = fan2.class;
Field[] fields = clazz.getDeclaredFields();
Method[] methods = clazz.getDeclaredMethods();
for (Method a : methods) {
System.out.println(a);
}
}
}
class fan2 {
private String name;
public int age;
public fan2(String name,int age) {
this.name = name;
this.age = age;
}
private void echo() {
System.out.println("my name is "+name+"and i am "+age+" old");
}
}

output:
private void test2.fan2.echo()

可以发现Method并不能获取到构造方法,构造方法又专门的类来获取。invoke得到方法之后可以执行:

getMethod:是获取方法

invoke是执行方法,里面放的是实例化类

newInstance()是对类的实例化

Constructor

Constructor提供了有关类的构造方法信息。

image.png

实例:

package test2;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class fan1 {
public static <T> void main(String[] args) throws ClassNotFoundException {
Class clazz = fan2.class;
Field[] fields = clazz.getDeclaredFields();
try {
Field fields2 = clazz.getDeclaredField("name");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Field a:fields) {
System.out.println(a);
}
Method[] methods = clazz.getDeclaredMethods();
for (Method a : methods) {
System.out.println(a);
}
Constructor<?>[] cont = clazz.getDeclaredConstructors();
for(int i = 0;i < cont.length; i++) {
System.out.println(cont[i]);
}
}
}
class fan2 {
private String name;
public int age;
public fan2(String name,int age) {
this.name = name;
this.age = age;
System.out.println("there is 2 parame");
}
public  fan2() {
System.out.println("there is no parame");
}
private void echo() {
System.out.println("my name is "+name+"and i am "+age+" old");
}
}

output:

private java.lang.String test2.fan2.name
public int test2.fan2.age
private void test2.fan2.echo()
public test2.fan2(java.lang.String,int)
public test2.fan2()
安全问题

java反序列化漏洞离不开反射的利用。p神在知识星球写了一篇关于反射的文章给出了这么一个例子:

<br/>
Last modification:November 30th, 2020 at 11:05 am