java 不使用final关键字可以避免继承吗?

bcs8qyzn  于 2023-05-12  发布在  Java
关注(0)|答案(7)|浏览(128)

我只想知道我能有两个A类和B类。我不想让B类扩展A类。我应该在类A中应用什么技术,使类B不能继承类A。我可不想让A班进入决赛。除了让A类成为最终的解决方案之外,还有其他解决方案吗?

lx0bsm1f

lx0bsm1f1#

事实上,我尝试遵循的实践,以及Josh Bloch在他的Effective Java书中推荐的实践,正是您被告知的规则的逆规则:除非你已经考虑过继承,将你的类设计为可继承的,并记录了你的类必须如何被继承,否则你应该总是禁用继承。
我建议你阅读Effective Java的这一章(你不会后悔买了它),然后把它展示给告诉你这个规则的人。
不允许继承的最明显的原因是不变性。不可变对象使用简单(只有一种状态),可以缓存,在许多对象之间共享,并且本质上是线程安全的。如果类是可继承的,任何人都可以扩展该类,并通过添加可变属性使其可变。https://stackoverflow.com/a/10464466/5010396

ulydmbyx

ulydmbyx2#

这是不可能的“好的方式”。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不能模拟final类)。

djmepvbi

djmepvbi3#

你可以将A类的构造函数标记为private。:)
PS:如果你也想避免反射攻击,那么从构造函数中抛出一些错误,并将其标记为私有。

zbsbpyhn

zbsbpyhn4#

你可以选择在构造函数中进行这样的限制。

if (this.getClass() != MyClass.class) {
    throw new RuntimeException("Subclasses not allowed");
}

更多详情请查看帖子。
https://stackoverflow.com/a/451229/6742601

zaqlnxep

zaqlnxep5#

我不明白你的要求的具体用例,但这可能会起作用。

如果您愿意在B中进行更改

在B的每一个构造函数中,如果它是A的一个示例,那么就会抛出一个错误。

if(A.class.isAssignableFrom(B.class)) {
        System.out.println(true);
        throw new IllegalStateException();
    }
    else
        System.out.println(false);
jexiocij

jexiocij6#

您可以执行以下操作之一以避免继承,而无需使用final关键字:

  • 使用私有构造函数。
  • 将每个方法标记为final,这样子对象就不能覆盖它们。
  • 在构造函数中抛出运行时异常,如果想限制一些不需要的子对象的继承(尽管很粗鲁),例如

if (this.getClass() != FavoriteChild.class) throw new RuntimeException("Not Allowed")

brvekthn

brvekthn7#

1.将类的所有构造函数声明为private
1.使类包仍然受保护(默认访问修饰符/无访问修饰符),这将允许在同一个包中继承,但不允许在不同的包中继承

相关问题