Java 初始化子类字段
考虑一个简单的Java 初始化子类字段,java,initialization,field,subclass,extending,Java,Initialization,Field,Subclass,Extending,考虑一个简单的AClass: class AClass { private AContent content; AClass(AContent content) { this.content = content; print(); } protected void print() { System.out.println("AClass content is "+ content.getValue());
AClass
:
class AClass {
private AContent content;
AClass(AContent content) {
this.content = content;
print();
}
protected void print() {
System.out.println("AClass content is "+ content.getValue());
}
}
其中,a内容的定义如下:
class AContent {
int getValue() {
return 1;
}
}
class BContent extends AContent{
@Override
int getValue() {
return 2;
}
}
b类
,扩展了a类
,并由b内容
初始化,该内容扩展了a内容
,如下所示:
class BClass extends AClass {
private BContent content;
BClass(BContent content) {
super(content);
this.content = content;
}
@Override
protected void print() {
System.out.println("BClass content is "+ content.getValue());
}
}
其中,b内容
由以下内容定义:
class AContent {
int getValue() {
return 1;
}
}
class BContent extends AContent{
@Override
int getValue() {
return 2;
}
}
构造b类
对象:
public static void main(String[] args) {
new BClass(new BContent());
}
正如预期的那样,由于尝试打印而产生的NullPointerException
System.out.println("BClass content is "+ content.getValue());
在初始化内容之前
为了克服它,我考虑了两种选择:
a、 从构造函数中删除print()
调用。这将起作用,但对于我所需要的功能来说并不可取。
b、 将内容设置为静态,并使用静态方法对其进行初始化:
private static BContent content;
BClass(BContent content) {
super(init(content));
}
private static BContent init(BContent content) {
BClass.content = content;
return content;
}
这会起作用,但看起来很丑陋
我正在寻求有关如何更好地构造此类代码的建议,以使其不仅具有功能,而且符合常见做法。一种方法是将b内容
传递给AClass
构造函数。这将起作用,因为BContent
是AContent
的子类:
class AClass {
// Make protected so subclasses can access
// (probably better via a protected get method)
protected AContent content;
...
}
class BClass extends AClass {
BClass(BContent content) {
super(content);
}
@Override
protected void print() {
System.out.println("BClass content is "+ content.getValue());
}
}
当调用print
方法content
时,您的print
方法将已初始化,您就没事了
如果您确实需要在b类中知道b内容
的类型,请使用泛型:
class AClass<ContentT extends AContent> {
// Make protected so subclasses can access
// (probably better via a protected get method)
protected ContentT content;
...
}
class BClass extends AClass<BContent> {
BClass(BContent content) {
super(content);
}
@Override
protected void print() {
// Now if I wanted I could do things with BContent that aren't
// possible with AContent since the type of BContent is known
System.out.println("BClass content is "+ content.getValue());
}
}
类AClass{
//使其受保护,以便子类可以访问
//(通过受保护的get方法可能更好)
受保护的内容;
...
}
类BClass扩展了AClass{
B类(B内容){
超级(内容);
}
@凌驾
受保护的无效打印(){
//现在,如果我愿意,我可以用B内容做一些不需要的事情
//由于已知B内容的类型,因此可能使用A内容
System.out.println(“b类内容为”+content.getValue());
}
}
基于@Oliver Dain的回答,我最终得出:
class AClass <T extends AContent>{
private T content;
AClass(T content) {
this.content = content;
print();
}
protected void print() {
System.out.println("Content is "+ getContent().getValue());
}
public T getContent() {
return content;
}
}
class BClass extends AClass<AContent> {
BClass(BContent content) {
super(content);
}
public static void main(String[] args) {
new BClass(new BContent());
}
}
class AContent {
int getValue() {
return 1;
}
}
class BContent extends AContent{
@Override
int getValue() {
return 2;
}
}
类AClass{
私有内容;
AClass(T内容){
this.content=内容;
打印();
}
受保护的无效打印(){
System.out.println(“内容是”+getContent().getValue());
}
公共T getContent(){
返回内容;
}
}
类BClass扩展了AClass{
B类(B内容){
超级(内容);
}
公共静态void main(字符串[]args){
新的b类(新的b内容());
}
}
类内容{
int getValue(){
返回1;
}
}
类BContent扩展了AContent{
@凌驾
int getValue(){
返回2;
}
}
b类
将b内容
传递给AClass
构造函数,或者我遗漏了什么?您将其传递给AClass,但随后通过将其复制到具有相同名称的B类中的属性来复制和隐藏它。在上面的答案中,只有AClass引用了内容B类引用内容引用系统.out.println(“B类内容是”+content.getValue())代码>导致NullPointerException
,因为它尚未初始化。是的。但由于AClass是其父级,因此它可以从父级访问它。而且,由于父级在子级之前初始化,因此您将是安全的。你在这里试过这个建议,发现它不管用吗?