解决一个小问题,记录一下。
使用Class.forName(className).newInstance();创建具体类对象的时候,出现空指针异常,
排查过程中也检查了是否是基本问题引起:
待反射类名是否与实际实现类类名完全一致,拼写大小写检查等。
待反射类构造器是否有参,这需要与反射类型相匹配。
待反射类构造器访问修饰符检查。
但是Debug的时候Class.forName(className)这个部分确实不为空的,那只有一个原因就是对象初始化的问题。
直接上测试代码:
package com.seek.test;
/**
* 属性测试类
*/
public class TestProperty {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.seek.test;
/**
*
* 基本类
*/
public abstract class BaseClass {
private TestProperty testProperty;
static{
System.out.println("Loading BaseClass.");
}
protected void exeMethod(){
System.out.println("BaseClass exeMethod...");
}
protected TestProperty getTestProperty() {
return this.testProperty;
}
public void setTestProperty(TestProperty testProperty) {
this.testProperty = testProperty;
}
}
package com.seek.test;
/**
* 实现类
*
*/
public class ImplClass extends BaseClass{
// private TestProperty proterty;//实现类变量未作初始化的情况下,反射获取实现类对象会出现空指针异常
static{
System.out.println("Loading ImplClass.");
}
@Override
protected void exeMethod() {
System.out.println("ImplClass exeMethod : " + proterty.getName());
}
/**
* 调用父类方法为实现类变量进行初始化,但是父类变量未做初始化,实现类变量也未初始化成功,
* 此时,反射获取实现类对象会出现空指针异常
* PS : 这种把变量声明语句放在一堆方法之后的情况,排查这个问题尤其恶心。
*/
private TestProperty proterty = getTestProperty();
}
package com.seek.test;
/**
* 测试类
*/
public class ReflectTest {
public static void main(String[] args) {
try {
Class<?> class1 = Class.forName("com.seek.test.ImplClass");
System.out.println("class1 Name:" + class1.getName());
ImplClass impl = (ImplClass)class1.newInstance();
impl.exeMethod();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
执行结果:
Loading BaseClass.
Loading ImplClass.
class1 Name:com.seek.test.ImplClass
Exception in thread "main" java.lang.NullPointerException
at com.seek.test.ImplClass.exeMethod(ImplClass.java:11)
at com.seek.test.ReflectTest.main(ReflectTest.java:10)