java反射概念

Java反射机制是在运行状态时,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。

java反射基本用法

Person类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.ex.www;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class Person implements Serializable {
private transient String name;
private int age;
public Person() {

}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{"+
"name='" + name + '\'' +
", age=" + age +
'}';
}

public String action(String action) {
System.out.println(action);
return action;
}

private static void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
Runtime.getRuntime().exec("calc");
}

}

reflectionTest类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.ex.www;

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

public class reflectionTest {
public static void main(String[] args) throws Exception {
Person person = new Person();
Class c = person.getClass(); //获取类的元数据对象

//使用反射机制,实例化对象
Constructor personconstroctor = c.getConstructor(String.class,int.class); //通过反射机制获取Person类中接收一个String参数和一个int参数的public构造方法的引用(获取构造方法)
Person p = (Person) personconstroctor.newInstance("abc",25); //实例化成一个对象
System.out.println(p);

//使用反射机制,获取类里面的属性
Field[] personfields = c.getDeclaredFields();
for (Field f : personfields) {
System.out.println(f);
} //循环打印属性
Field nameField = c.getDeclaredField("name"); //从原型(类的元数据对象)里获取一个属性
nameField.setAccessible(true); //允许更改(无论是privated,还是protected)
nameField.set(p,"ssss"); //更改对象的值
System.out.println(p);
//使用反射机制,调用类里面的方法
Method[] personmethods = c.getDeclaredMethods(); //
for (Method m : personmethods) {
System.out.println(m);
}

Method nameMethod = c.getDeclaredMethod("action", String.class);
nameMethod.setAccessible(true);
nameMethod.invoke(p, "abc"); //调用action方法传入参数为abc

}
}

全在注释里面哦

反射的应用

一个简单的使用,一个关于dns的。

也就是使用hashmap作为一个入口调用url对象下的hashcode函数

img

继续跟进

img

做了一个DNS。

但是我们肯定要向hashmap投入一个键值,所以要使用到put

img

我们跟进put

img

跟进hash方法

img

发现这里调用了一个hashcode,

img

由于初值是-1所以put的时候就会出现一次dns的解析

最后返回的是hashCode,然后我们序列化之后就不是-1了,所以反序列化时就不会进行dns解析了。

根据以上,我们需要第一次不进行dns解析,同时要让反序列化时,进行DNS,因此我们要使用反射机制,进行更改。

img

这样即可。注意点setaccessible方法在17版本是不可用的了,要使用别的方法进行更改私有属性,或者对改一下jdk版本