- 0x01 前言
- 0x02 获得类实例的方法
- 0x02.1 例子-类(用于理解的)
- 0x02.2 类的.class语法
- 0x02.3 对象的getClass()方法
- 0x02.4 通过-类加载器
- 0x02.5 Class的静态方法 forName(String classPath)
- 0x02.5.1 实例化-例子
- 0x02.5.2 额外知识一
- 0x02.5.2.1 String[].class-JNI字段描述符
- 0x02.5.2.2 Object[].class-JNI字段描述符
- 0x02.5.2.3 Integer[].class-JNI字段描述符
- 0x02.5.2.4 Boolean[].class-JNI字段描述符
- 0x02.5.2.5 byte[].class-JNI字段描述符
- 0x02.5.2.6 char[].class-JNI字段描述符
- 0x02.5.2.7 short[].class-JNI字段描述符
- 0x02.5.2.8 int[].class-JNI字段描述符
- 0x02.5.2.9 long[].class-JNI字段描述符
- 0x02.5.2.10 float[].class-JNI字段描述符
- 0x02.5.2.11 double[].class-JNI字段描述符
- 0x02.5.3 额外知识二
0x01 前言
了解到如何获取一个类的Class对象是我们入门反射的第一步。
因为在Java中反射操作的是java.lang.Class对象。
因此我们需要学会的第一步就是如何获取到Class对象, 为后面打好基础。
0x02 获得类实例的方法
0x02.1 例子-类(用于理解的)
// 例如现在有一个 Foo类// 请实例化它并调用 print() 方法// 额外提问: 它没有构造方法,能不能被反射new呢?// 答案是可以的,在本文0x02.5.1中可以看得到结果package 反射;class Foo {void print() {System.out.println("foo的print方法冲冲冲");}}
0x02.2 类的.class语法
package 反射;public class Test {public static void main(String[] args) {Class fooClass1 = Foo.class;try {Foo foo = (Foo) fooClass1.newInstance();foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
# 运行结果foo的print方法冲冲冲进程已结束,退出代码 0
0x02.3 对象的getClass()方法
package 反射;public class Test {public static void main(String[] args) {Foo f = new Foo();Class fooClass2 = f.getClass();try {Foo foo = (Foo) fooClass2.newInstance();foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
# 运行结果foo的print方法冲冲冲进程已结束,退出代码 0
0x02.4 通过-类加载器
package 反射;public class Test {public static void main(String[] args) {Class fooClass3 = null;try {fooClass3 = ClassLoader.getSystemClassLoader().loadClass("反射.Foo");} catch (ClassNotFoundException e) {e.printStackTrace();}try {Foo foo = (Foo) fooClass3.newInstance();foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
# 运行结果foo的print方法冲冲冲进程已结束,退出代码 0
0x02.5 Class的静态方法 forName(String classPath)
0x02.5.1 实例化-例子
package 反射;public class Test {public static void main(String[] args) {Class fooClass4 = null;try {fooClass4 = Class.forName("反射.Foo");} catch (ClassNotFoundException e) {e.printStackTrace();}try {// 注意: 如果反射的这个类,没有构造方法,那么也是可以被new出来的// 因为Java的类没有构造方法的时候,也会为类添加一个默认的空构造方法// 记得这一点,代码审计时遇到可控Class.forName但是不可控newInstance()的情况// 那么就可以去找那种没有设置构造方法的工具类,进行实例化Foo foo = (Foo) fooClass4.newInstance();foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
# 运行结果foo的print方法冲冲冲进程已结束,退出代码 0
0x02.5.2 额外知识一
如果说获取的Class对象为数组类型的话,需要特殊注意。
这种情况需要使用 Java JNI字段描述符
注意事项:一个数组 [Ljava.lang.String;二维数组 [[Ljava.lang.String;三维数组 [[[Ljava.lang.String;
0x02.5.2.1 String[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> stringArray = Class.forName("[Ljava.lang.String;");Class<String[]> test = String[].class;System.out.println(stringArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.2 Object[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> objectArray = Class.forName("[Ljava.lang.Object;");Class<Object[]> test = Object[].class;System.out.println(objectArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.3 Integer[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> integerArray = Class.forName("[Ljava.lang.Integer;");Class<Integer[]> test = Integer[].class;System.out.println(integerArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.4 Boolean[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> booleanArray = Class.forName("[Ljava.lang.Boolean;");Class<Boolean[]> test = Boolean[].class;System.out.println(booleanArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.5 byte[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> byteArray = Class.forName("[B");Class<byte[]> test = byte[].class;System.out.println(byteArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.6 char[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> charArray = Class.forName("[C");Class<char[]> test = char[].class;System.out.println(charArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.7 short[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> shortArray = Class.forName("[S");Class<short[]> test = short[].class;System.out.println(shortArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.8 int[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> intArray = Class.forName("[I");Class<int[]> test = int[].class;System.out.println(intArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.9 long[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> longArray = Class.forName("[J");Class<long[]> test = long[].class;System.out.println(longArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.10 float[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> floatArray = Class.forName("[F");Class<float[]> test = float[].class;System.out.println(floatArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.2.11 double[].class-JNI字段描述符
public class JNITest {public static void main(String[] args) {try {Class<?> doubleArray = Class.forName("[D");Class<double[]> test = double[].class;System.out.println(doubleArray == test);} catch (ClassNotFoundException e) {e.printStackTrace();}}}
0x02.5.3 额外知识二
# 在使用 Class.forName() 调用内部类的时候需要使用 $符号 来代替 .(点号)# 例如现在有一个 com.alibaba.Test里面有一个内部类叫Hello# 然后现在想调用 om.alibaba.Test 里面的 Hello类# 那么调用的时候就应该这么写 com.alibaba.Test$Hello# 换成代码就是public class Test {public static void main(String[] args) {Class tClass = null;try {tClass = Class.forName("com.alibaba.Test$Hello");} catch (ClassNotFoundException e) {e.printStackTrace();}}}
