我只想知道我能有两个A类和B类。我不想让B类扩展A类。我应该在类A中应用什么技术,使类B不能继承类A。我可不想让A班进入决赛。除了让A类成为最终的解决方案之外,还有其他解决方案吗?
lx0bsm1f1#
事实上,我尝试遵循的实践,以及Josh Bloch在他的Effective Java书中推荐的实践,正是您被告知的规则的逆规则:除非你已经考虑过继承,将你的类设计为可继承的,并记录了你的类必须如何被继承,否则你应该总是禁用继承。我建议你阅读Effective Java的这一章(你不会后悔买了它),然后把它展示给告诉你这个规则的人。不允许继承的最明显的原因是不变性。不可变对象使用简单(只有一种状态),可以缓存,在许多对象之间共享,并且本质上是线程安全的。如果类是可继承的,任何人都可以扩展该类,并通过添加可变属性使其可变。https://stackoverflow.com/a/10464466/5010396
ulydmbyx2#
这是不可能的“好的方式”。java语言允许你在类定义中使用final关键字,或者不使用。正如其他人所指出的:你可以让所有的构造函数都是私有的,那么子类化就变得几乎不可能了,因为子类构造函数没有超类构造函数可以调用。如果你需要示例化A,你仍然可以有一个工厂方法,比如:
final
public class A { private A() { ... } private A(String foo) { ... } public static A newInstance(String foo) { return new A(foo); }
例如。但请记住:代码是为人类读者编写的。如果你的意图是要有一个最终类,那么 * 正确 * 答案是使用关键字final。另外:使类成为final允许JIT做更多的事情,因为它在任何时候都不必担心多态性(因此它可以直接内联方法代码,而无需任何额外的检查)。因此使用final可以略微提高性能。另一方面,它限制了你对事物进行单元测试的能力(例如:标准的Mockito不能模拟final类)。
djmepvbi3#
你可以将A类的构造函数标记为private。:)PS:如果你也想避免反射攻击,那么从构造函数中抛出一些错误,并将其标记为私有。
zbsbpyhn4#
你可以选择在构造函数中进行这样的限制。
if (this.getClass() != MyClass.class) { throw new RuntimeException("Subclasses not allowed"); }
更多详情请查看帖子。https://stackoverflow.com/a/451229/6742601
zaqlnxep5#
我不明白你的要求的具体用例,但这可能会起作用。
如果您愿意在B中进行更改
B
在B的每一个构造函数中,如果它是A的一个示例,那么就会抛出一个错误。
if(A.class.isAssignableFrom(B.class)) { System.out.println(true); throw new IllegalStateException(); } else System.out.println(false);
jexiocij6#
您可以执行以下操作之一以避免继承,而无需使用final关键字:
if (this.getClass() != FavoriteChild.class) throw new RuntimeException("Not Allowed")
brvekthn7#
1.将类的所有构造函数声明为private1.使类包仍然受保护(默认访问修饰符/无访问修饰符),这将允许在同一个包中继承,但不允许在不同的包中继承
7条答案
按热度按时间lx0bsm1f1#
事实上,我尝试遵循的实践,以及Josh Bloch在他的Effective Java书中推荐的实践,正是您被告知的规则的逆规则:除非你已经考虑过继承,将你的类设计为可继承的,并记录了你的类必须如何被继承,否则你应该总是禁用继承。
我建议你阅读Effective Java的这一章(你不会后悔买了它),然后把它展示给告诉你这个规则的人。
不允许继承的最明显的原因是不变性。不可变对象使用简单(只有一种状态),可以缓存,在许多对象之间共享,并且本质上是线程安全的。如果类是可继承的,任何人都可以扩展该类,并通过添加可变属性使其可变。https://stackoverflow.com/a/10464466/5010396
ulydmbyx2#
这是不可能的“好的方式”。java语言允许你在类定义中使用
final
关键字,或者不使用。正如其他人所指出的:你可以让所有的构造函数都是私有的,那么子类化就变得几乎不可能了,因为子类构造函数没有超类构造函数可以调用。
如果你需要示例化A,你仍然可以有一个工厂方法,比如:
例如。
但请记住:代码是为人类读者编写的。如果你的意图是要有一个最终类,那么 * 正确 * 答案是使用关键字
final
。另外:使类成为final允许JIT做更多的事情,因为它在任何时候都不必担心多态性(因此它可以直接内联方法代码,而无需任何额外的检查)。因此使用
final
可以略微提高性能。另一方面,它限制了你对事物进行单元测试的能力(例如:标准的Mockito不能模拟final类)。djmepvbi3#
你可以将A类的构造函数标记为private。:)
PS:如果你也想避免反射攻击,那么从构造函数中抛出一些错误,并将其标记为私有。
zbsbpyhn4#
你可以选择在构造函数中进行这样的限制。
更多详情请查看帖子。
https://stackoverflow.com/a/451229/6742601
zaqlnxep5#
我不明白你的要求的具体用例,但这可能会起作用。
如果您愿意在
B
中进行更改在B的每一个构造函数中,如果它是A的一个示例,那么就会抛出一个错误。
jexiocij6#
您可以执行以下操作之一以避免继承,而无需使用
final
关键字:final
,这样子对象就不能覆盖它们。if (this.getClass() != FavoriteChild.class) throw new RuntimeException("Not Allowed")
brvekthn7#
1.将类的所有构造函数声明为private
1.使类包仍然受保护(默认访问修饰符/无访问修饰符),这将允许在同一个包中继承,但不允许在不同的包中继承