本文翻译于一片国外文章,原文链接如下:Tatu Saloranta
JackSon和内部类,是的,你可以使用,但他们必须是静态的内部类。
这是我直到今天没有意识到的东西:这显然是正确使用内部类在Java开发者社区的巨大的困惑。事实上有一些网页显示
JackSon不能使用内部类值。
这实际上是真实的和虚假的,原因就在于Java的内部类的特点。早在Java 1.1的时候就引入了内部类(为了使AWT以及后
来的Swing更容易使用),但不是每个人都懂得如何适当地使用内部类。
1.长话短说
你可以这样使用静态内部类:
public class Outer {
static class Inner {
public int getX() { return 5;
}
}
值没有任何问题。只要确保“静”在那里。
如果你的内部类不是静态的,那么所得到的类通常是JackSon以及任何其他数据绑定框架无用(Hibernate,JAXB)不可以
使用的;通常可以被序列化,但不可以反序列化。要理解为什么,需要我们回到过去,90年代末…第一批语法糖加入Java
。
2.匿名的,静态的,非静态内部类
一共有三种内部类形式:匿名内部类是在一条语句中使用的 (如事件处理函数); 静态内部类是用static修饰符修饰的类
; 普通内部类类似静态内部类,区别在于没有static修饰.
这里最重要的区别在于有么有static修饰. 修饰符选择不是很直观的, 它真正的意思是:非静态内部类(包括匿名内部类
)被编译器通过隐藏的构造器传递了一组隐藏变量.直接结果就是, 无默认构造函数 -- 即使代码里面确实有一个无参的
构造函数可以使用。
所以,如果你的代码是这样写的:
public class Outer {
class Inner { // non-static
public int getX() { return 3; }
}
}
实际上编译器会这样生成:
public class Outer { ... }
class Outer$Inner {
private final Outer parent;
Outer$Inner(Outer p) {
parent = p;
}
public int getX() { return 3; }
}
(同样的,内部类可以访问外部类的所有代码)
为什么会这样? 因为这样内部类内部就可以访问外部类的所有代码,包括私有代码;在匿名的情况下(内置)内部类,
甚至看似范围内的变量(这只是雾里看花 - 最后变量作为传递只是更隐蔽构造函数的参数)。
静态内部类只是普通的类,无任何隐藏内容。实际上它跟二级类(含有公开类的文件中声明的非公开类,使用封闭的命名
空间)除名字以外并无本质区别。
3。所以关于JackSon,内部类…?
JackSon拒绝尝试使用非静态内部类的基本原因(序列化是可以正常工作的)是因为这样的类没有实例化的一般方法,没
有零参数的构造函数,也没有@jsoncreator注释其他构造函数或工厂方法(或单个字符串参数的构造函数),所以
JackSon不能实例化它们。
在理论上可以如果得知所包围的父类实例是什么,那么就可以处理这种情况。但实际上这是复杂的和不必要的——典型的
static缺失是意外或者疏忽,通过增加给内部类增加static就可以让代码很好的工作。