不使用"final"关键字实现一个最终类

12

几天前,我的一个朋友在电话面试中被问到了这个问题。我一无所知。有人能提供解决方案吗?(他的面试已经结束了,只是出于好奇)10x。


4
如果我回答那个面试问题,我会说:“如果我想要一个final类,我会使用该死的final关键字。它存在是有原因的。”我知道他们可能想了解面试者的创造力,但有比询问如何避免充分利用语言更好的方法。 - Rob Hruska
@Rob: 我个人认为这是问题的一部分。答案的很大一部分是下面的技巧,但是如果一个候选人能够说“当然,这给出了final类的'不能扩展'语义,但是由于它们在技术上并不是final,所以有些优化HotSpot可能没有意识到可以做的......等等。”那么肯定也是额外的加分项。两部分都表明了对final的相关性的了解,而后一部分则展示了对代码的"好"和"坏"的意识,而不仅仅是"功能上正确"的代码。 - Andrzej Doyle
@Andrzej Doyle - 理解了。我想这取决于面试官以及他们如何处理这个问题。我承认我的评论有些过激。 - Rob Hruska
7个回答

12
  • 将构造函数标记为私有
  • 在类上提供一个静态方法来创建该类的实例。这将允许您实例化该类的对象。

1
如果你想避免不安全的发布,可以将你的字段标记为 volatile - Tom Hawtin - tackline
当使用"final"关键字与提议的两行代码一起使用时,它是否具有额外的好处?@byte - Gnanz
1
正确,但这只能防止对象创建。 但是最终类无法被覆盖,所以问题是如何防止继承? 如何停止类被继承(不使用final)? - Nishant Shah

0
如何创建一个没有参数的私有构造函数?
public class Base
{
    private Base()
    {
    }
}

public class Derived : Base
{
//Cannot access private constructor here error
}

0
public class Immutable {       
    private int val;

    public Immutable(int v)
    { 
        this.val = v;
    }

    public int getVal() { return this.val; }
}

3
你能在你的回答中加入一些解释吗? - Joe Kennedy

0

我不太明白他们所说的final类到底是什么意思。如果他们指的是一个不能被继承的类,那显然除了将这个类标记为final(或者sealed,或者其他语言关键字),就无法实现。

但如果他们所说的final是指不可变的,也就是派生类无法修改该类中字段的值,那么基类中应该将所有字段和访问器方法都设为私有。


1
如果他们的意思是一个不能被继承的类,那么很明显除了将该类标记为final之外,这是不可能实现的。但是这也可以通过将构造函数设为私有来实现。 - Péter Török

0
将该类的所有构造函数设为私有以阻止继承,虽然这并不被推荐。

0

你可以在不使用final关键字的情况下使你的类成为不可变类,具体步骤如下:

  1. 将实例变量设为私有。
  2. 将构造函数设为私有。
  3. 创建一个工厂方法来返回该类的实例。

我在这里提供了一个在Java中的不可变类。

class Immutable {
    private int i;
    private Immutable(int i){
     this.i = i;
    }
    public static Immutable createInstance(int i){
         return new Immutable(i);
    }
    public int getI(){return i;}
}
 class Main {
    public static void main(string args[]){
       Immutable obj = Immutable.createInstance(5);
    }
}

你的代码中有一些错误。首先,createInstance方法缺少返回类型。而最大的问题是不能在静态上下文中使用this。还有一个建议是应该尝试使用equals,而不是this.i == i。但这并不重要,因为createInstance方法无法正常工作。总之,做得不错。 - Evgeni Enchev
谢谢指出我的错误。我已经更新了我的代码。@EvgeniEnchev - salman94

-1

静态类无法被继承


你尝试创建一个继承自静态类的类。这是不可能的。就所有目的而言,静态类是final/sealed的。 - Xhalent
public class Test { static class A {} static class B extends A{} public static void main(String [] args) throws Exception { B b = new B(); System.err.println(""+b); } } 将其粘贴到 Test.java 中,编译并运行。 - khachik
在使用final关键字的语言中,如何表达“static classes”?必须要使用可以被扩展的静态嵌套类。 - Tom Hawtin - tackline

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接