Java中的最终接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2971881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:03:11  来源:igfitidea点击:

Final interface in Java?

javaoop

提问by JavaUser

Can an interface be declared as final in Java?

接口可以在 Java 中声明为 final 吗?

采纳答案by Igor Zevaka

Interfaces are 100% abstract and the only way to create an instance of an interface is to instantiate a class that implements it. Allowing interfaces to be finalis completely pointless.

接口是 100% 抽象的,创建接口实例的唯一方法是实例化一个实现它的类。允许接口final是完全没有意义的。

EDITThe questions is not as outright outrageous as I first thought. A final interface is one that cannot be extended by other interfaces but can be implemented ostensibly makes sense.

编辑这些问题并不像我最初想的那样完全离谱。最终接口是一个不能被其他接口扩展但表面上可以实现的接口。

I could think of one difference between a final class and a final interface. Extending a class can compromise its integrity because it contains some state. Extending an interface simply adds operations and cannot compromise the integrity of the implementation because the interface is stateless on its own.

我可以想到最终类和最终接口之间的一个区别。扩展类可能会损害其完整性,因为它包含一些状态。扩展接口只是添加操作,不会损害实现的完整性,因为接口本身是无状态的。

回答by Jordan Lewis

No. Trying to declare an interface as final in Java results in a compilation error. This is a language design decision - Java interfaces are meant to be extendable.

否。尝试在 Java 中将接口声明为 final 会导致编译错误。这是一个语言设计决定——Java 接口是可扩展的。

回答by bakkal

From the Java Language Specification (Third Edition):

来自 Java 语言规范(第三版):

9.1.1.1 abstract Interfaces

Every interface is implicitly abstract. This modifier is obsolete and should not be used in new programs.

9.1.1.1 抽象接口

每个接口都是隐式的 abstract。此修饰符已过时,不应在新程序中使用。

So, abstract+ finalis sort of an oxymoron.

所以,abstract+final有点矛盾。

回答by aioobe

No. The Java Language Specification section 9.1.1. Interface Modifiers states the following:

否。Java 语言规范第9.1.1接口修饰符声明如下:

An interface declaration may include interface modifiers.

InterfaceModifier:
  (one of)
  Annotation public protected private
  abstract static strictfp

接口声明可以包括接口修饰符。

InterfaceModifier:
  (one of)
  Annotation public protected private
  abstract static strictfp

As can be seen, the list does not include final.

可以看出,该列表不包括final.

Why was the language designed this way?

为什么语言是这样设计的?

If an interface was declared finalI suppose it could have meant that

如果声明了一个接口,final我想这可能意味着

  • No other interface could extend it

    This would be a non-sensical restriction. The reasons for why it can be useful to declare a classfinal, is to protect state invariants, prohibit overriding of all methods at once, etc. None of these restrictions makes sense for interfaces. (There is no state, and all methods mustbe overridden.)

  • No class could implement the interface

    This obviously defeats the purpose of an interface altogether.

  • 没有其他接口可以扩展它

    这将是一个无意义的限制。将声明为final有用的原因是保护状态不变量、禁止一次覆盖所有方法等。这些限制对接口都没有意义。(没有状态,必须覆盖所有方法。)

  • 没有类可以实现接口

    这显然完全违背了接口的目的。

回答by gmhk

Instead of Declaring Interface as a Final, We can avoid Creating an Interface object.

我们可以避免创建接口对象,而不是将接口声明为 Final。

Point of Creating Interface to implements its methods by its subclass. If we are defeating this purpose then I feel its a baseless.

创建接口的点以通过其子类实现其方法。如果我们打败了这个目的,那么我觉得这是毫无根据的。

If any have any other suggestions, kindly let us know

如果有任何其他建议,请告诉我们

回答by Peter Lawrey

While a final interface would still have uses, none of them are widely considered good practice.

虽然最终接口仍然有用,但它们都不是被广泛认为的良好实践。

A final interface could be used for

最终接口可用于

  • defining constants. Generally considered a bad idea.
  • meta-information to be examined via reflection, e.g. a package descriptor
  • grouping together many public inner classes into one file. (I only suggest this is used when cut-and-pasting some sample code which has many classes as it saves you the hassle of creating a file for each class, inner classes are implicitly static)
  • 定义常量。通常被认为是一个坏主意。
  • 要通过反射检查的元信息,例如包描述符
  • 将许多公共内部类组合到一个文件中。(我只建议在剪切和粘贴一些具有许多类的示例代码时使用它,因为它可以为您节省为每个类创建文件的麻烦,内部类是隐式静态的)

You can do all these things with a non-final interface and marking an interface as final would not be as useful as a comment saysing you are using an interface for an incedental purpose and why you are doing so

您可以使用非最终界面来完成所有这些事情,并且将界面标记为最终界面不会像评论说您将界面用于偶然目的以及为什么要这样做那么有用

回答by emory

I tried it and apparently you can create a final interface in java. I have no idea why you would do this, but you can. This is how I did it.

我试过了,显然你可以在java中创建一个最终界面。我不知道你为什么要这样做,但你可以。我就是这样做的。

  1. Compile a non final interface. I saved the below code in FinalInterface.java. Then I compiled it.

    interface FinalInterface { }

  2. Run BCELifier on it. This created a file called FinalInterfaceCreator.java

  3. Edit it. Look for a line similar to below and add ACC_FINAL.

    _cg = new ClassGen("FinalInterface", "java.lang.Object", "FinalInterface.java", ACC_INTERFACE | ACC_ABSTRACT | ACC_FINAL , new String[] { });

  4. Compile and run the edited FinalInterfaceCreator.java. This should overwrite the original FinalInterface.class file with a new one that is similar but final.

  1. 编译一个非最终接口。我将以下代码保存在 FinalInterface.java 中。然后我编译了它。

    接口最终接口{}

  2. 在其上运行 BCELifier。这创建了一个名为 FinalInterfaceCreator.java 的文件

  3. 编辑它。查找类似于下面的行并添加 ACC_FINAL。

    _cg = new ClassGen("FinalInterface", "java.lang.Object", "FinalInterface.java", ACC_INTERFACE | ACC_ABSTRACT | ACC_FINAL , new String[] { });

  4. 编译并运行编辑好的 FinalInterfaceCreator.java。这应该用一个类似但最终的新文件覆盖原始 FinalInterface.class 文件。

To test it, I created two new java files TestInterface and TestClass. TestInterface is an interface that extends FinalInterface and TestClass is a class that implements FinalInterface. The compiler refused to compile either because FinalInterface is final.

为了测试它,我创建了两个新的 java 文件 TestInterface 和 TestClass。TestInterface 是一个扩展 FinalInterface 的接口,TestClass 是一个实现 FinalInterface 的类。编译器拒绝编译,因为 FinalInterface 是最终的。

TestClass.java:2: cannot inherit from final FinalInterface
class TestClass implements FinalInterface

TestInterface.java:2: cannot inherit from final FinalInterface
interface TestInterface extends FinalInterface

In addition, I tried creating an instance of FinalInterface using dynamic proxies

此外,我尝试使用动态代理创建一个 FinalInterface 实例

class Main
{
    public static void main ( String [ ] args )
    {
    Class < ? > ntrfc = FinalInterface . class ;
    ClassLoader classLoader = ntrfc . getClassLoader ( ) ;
    Class < ? > [ ] interfaces = { ntrfc } ;
    java . lang . reflect . InvocationHandler invocationHandler = new java . lang . reflect . InvocationHandler ( )
        {
        public Object invoke ( Object proxy , java . lang . reflect . Method method , Object [ ] args )
        {
            return ( null ) ;
        }
        } ;
    FinalInterface fi = ( FinalInterface ) ( java . lang . reflect . Proxy . newProxyInstance ( classLoader , interfaces , invocationHandler ) ) ;
    }
}

This one compiled but did not run

这个编译了但没有运行

Exception in thread "main" java.lang.ClassFormatError: Illegal class modifiers in class FinalInterface: 0x610
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:632)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:277)
at java.net.URLClassLoader.access
package org.apidesign.demo.finalinterface;

import java.util.Collection;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import org.openide.util.lookup.ServiceProvider;

@ServiceProvider(service = Processor.class)
@SupportedAnnotationTypes("*")
public final class FinalEnforcingProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        checkForViolations(roundEnv.getRootElements());
        return true;
    }

    private void checkForViolations(Collection<? extends Element> all) {
        for (Element e : all) {
            if (e instanceof TypeElement) {
                TypeElement te = (TypeElement) e;
/* exception for the only known implementation:
if ("org.apidesign.demo.finalinterface.AllowedImplementationTest".equals(
  te.getQualifiedName().toString())
) continue;
*/
                for (TypeMirror m : te.getInterfaces()) {
                    if (FinalInterface.class.getName().equals(m.toString())) {
                        processingEnv.getMessager().printMessage(
                          Diagnostic.Kind.ERROR, "Cannot implement FinalInterface", e
                        );
                    }
                }
            }
            checkForViolations(e.getEnclosedElements());
        }
    }
 }
0(URLClassLoader.java:73) at java.net.URLClassLoader.run(URLClassLoader.java:212) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:319) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) at java.lang.ClassLoader.loadClass(ClassLoader.java:264) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:332) at Main.main(Main.java:6)

So the evidence suggests that you can create a final interface in java, but why would you want to?

因此,证据表明您可以在 Java 中创建最终接口,但您为什么要这样做呢?

回答by emory

Whenever you create an annotation you are creating an interface that is in some ways effectively final.

每当您创建注释时,您都在创建一个在某些方面有效的最终界面。

回答by Jaroslav Tulach

When designing APIs in JavaI sometimes find a situation where a type in the API has to be Java interface, but the number of its implementations should be limited - e.g. only the APIs internals can implement it, not anyone else.

在用Java设计 API 时,我有时会发现API 中的类型必须是 Java interface,但其实现的数量应该受到限制 - 例如,只有 API 内部可以实现它,其他人不能。

I realized I can now (since Java1.6) restrict who implements an interface with the help of annotation processors (article on apidesign.org). This is the code:

我意识到我现在可以(从Java1.6 开始)在注释处理器的帮助下限制谁实现接口(apidesign.org 上的文章)。这是代码:

##代码##

Everytime somebody includes your API JAR on classpath and tries to compile against it, the Javaccompiler invokes your annotation processor and let's you fail the compilation if it detects somebody else is trying to implement your interface.

每次有人在类路径中包含您的 API JAR 并尝试针对它进行编译时,Javac编译器都会调用您的注释处理器,如果它检测到其他人正在尝试实现您的接口,就会让您的编译失败。

I still prefer usage of final classfor Client API- e.g. an API that others are only allowed to call, but when it is not possible, the trick with annotation processoris acceptable alternative.

我还是比较喜欢的使用最后一类客户端API-例如别人只允许调用的API,但是当它是不可能的,有注释处理器招是可以接受的选择。

回答by Roy Alilin

final means it can't be modified. If it's a class, it can't be modified by extending (methods can be modified by overriding, attribute's can't be modified; added attributes/methods can only be accessed as members of the 'subclass type'); if its a variable (attribute/local) then the value can't be modified after first assignment; if its a method, the implementation can't be modified (a final method can be overloaded but can't be overridden). There no point in declaring an interface final since there's normally no implementation to modify (default and static interface methods are not allowed to be final).

final 意味着它不能被修改。如果是类,则不能通过扩展修改(方法可以通过覆盖修改,属性不能修改;添加的属性/方法只能作为“子类类型”的成员访问);如果它是一个变量(属性/本地),则在第一次赋值后不能修改该值;如果是方法,则无法修改实现(最终方法可以重载但不能被覆盖)。声明接口 final 没有意义,因为通常没有要修改的实现(默认和静态接口方法不允许是 final)。