我只想知道我可以有2个A类和B类。 我不想让B类扩展A类。 我应该在A类中应用什么技术,以便B类不能继承A类。 不想打入A级决赛。还有其他解决方案,而不是将A类定为最终解决方案?
答案 0 :(得分:2)
实际上,我尝试遵循的做法,以及乔什·布洛赫(Josh Bloch)在他的《有效的Java》一书中所建议的,恰恰是您所学的相反的规则:除非您考虑过继承,否则请设计类要被继承,并记录必须如何继承类,则应始终禁用继承。
我建议您阅读本章“有效的Java”(您不会后悔的),并向告诉您此规则的人展示。
禁止继承的最明显原因是不可变性。不可变的对象易于使用(只有一个状态),可以被缓存,可以在许多对象之间共享,并且本质上是线程安全的。如果该类是可继承的,则任何人都可以扩展该类,并通过添加可变属性来使其可变。 https://stackoverflow.com/a/10464466/5010396
答案 1 :(得分:1)
这不可能以“很好的方式”进行。 Java语言允许您在类定义中使用final
关键字,也可以不使用。
正如其他人所指出的:您可以将所有构造函数设为私有,然后子类化实际上变得不可能,因为子类构造函数没有父类构造函数可以调用。
如果需要实例化A,您仍然可以使用工厂方法,例如:
public class A {
private A() { ... }
private A(String foo) { ... }
public static A newInstance(String foo) { return new A(foo); }
例如。
但是请记住:代码是为人类读者编写的。如果您的意图要参加最后一堂课,那么正确答案是使用该关键字final
。
加上:将您的类定为final可以使JIT做更多的事情,因为它不必随时担心多态性(因此它可以直接内联方法代码,而无需任何其他检查)。因此,使用final
可以稍微改善性能。另一方面,它限制了您对事物进行单元测试的能力(例如:标准Mockito无法模拟最终课程)。
答案 2 :(得分:1)
您可以将A类的构造函数标记为私有。 :)
PS:如果您还想避免反射攻击,请向构造函数抛出一些错误 并将其标记为私有。
答案 3 :(得分:0)
我不了解您的需求的特定用例,但这可能行得通。
如果您愿意在B
进行更改
在B的每个构造函数中检查它是否是A的一个实例,然后引发错误。
if(A.class.isAssignableFrom(B.class)) {
System.out.println(true);
throw new IllegalStateException();
}
else
System.out.println(false);
答案 4 :(得分:0)
实际上,您可以将类A
放在没有修饰符的包中(package modifier
)。
package com.example.package1;
// Class A with package modifier.
class A {
}
并将类B
放在另一个包中
package com.example.package2;
// Class B cannot extends from class A, compiler error.
public class B extends A {
}
限制是,只有同一包中的类才能从类A
扩展。
答案 5 :(得分:0)
您可以选择这样限制构造函数。
if (this.getClass() != MyClass.class) {
throw new RuntimeException("Subclasses not allowed");
}
有关更多详细信息,请查看帖子。
答案 6 :(得分:0)
您可以执行以下一项操作来避免继承而不使用final
关键字:
final
,以使子代无法覆盖它们。if (this.getClass() != FavoriteChild.class) throw new RuntimeException("Not Allowed")