没有无参构造方法怎么实例化
如果一个类没有无参构造方法,也没有类似单例模式里的静态方法,我们怎样通过反射实例化该类呢?
这就需要使用到getConstructor这个方法了,先反射获取构造方法,然后调用newInstance获取实例化对象,传入构造函数所需要的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package org.javasec.FirstReflect;
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List;
public class TestPro { static void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class<?> clazz = Class.forName("java.lang.ProcessBuilder"); Method start = clazz.getMethod("start"); Constructor<?> ctor = clazz.getConstructor(List.class); start.invoke(ctor.newInstance(Arrays.asList("calc"))); } }
|
除此之外,还能使用强制类型转换,把实例化出来的ProcessBuilder当成一个整体,调用其start方法,而不是反射获取start方法了
1 2 3 4 5 6
| public class TestPro { static void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Class<?> clazz = Class.forName("java.lang.ProcessBuilder"); ((ProcessBuilder) clazz.getConstructor(List.class).newInstance(Arrays.asList("calc"))).start(); } }
|
怎么调用可变长参数型的构造方法
可变长参数
对于可变长参数,Java其实在编译的时候会编译成一个数组,也就是说,下面两种写法在底层上是等价的
1 2
| public void hello(String[] tests); public void hello(String...tests);
|
因此对于一个hello(String...tests)函数,我们传参时,直接传入数组就能直接接收参数
回到问题,在反射中,我们怎么调用构造方法接收的参数是可变长参数的情况呢?同理,当成数组调用就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package org.javasec.FirstReflect;
import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List;
public class TestPro { static void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Class<?> clazz = Class.forName("java.lang.ProcessBuilder"); ((ProcessBuilder) clazz.getConstructor(String[].class).newInstance(new String[][]{{"calc"}})).start(); } }
|
或者全部反射获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package org.javasec.FirstReflect;
import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List;
public class TestPro { static void test() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Class<?> clazz = Class.forName("java.lang.ProcessBuilder"); clazz.getMethod("start").invoke(clazz.getConstructor(String[].class).newInstance(new String[][]{{"calc"}})); } }
|
怎么调用私有构造方法
调用getDeclaredConstructor即可,注意修改它的作用域setAccessible
1 2 3 4
| Class clazz = Class.forName("java.lang.Runtime"); Constructor m = clazz.getDeclaredConstructor(); m.setAccessible(true); clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
|