第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java 接口是否可以定義為只有 Enum 可以擴展它?

Java 接口是否可以定義為只有 Enum 可以擴展它?

炎炎設計 2023-11-10 16:39:27
我想這樣做并沒有什么特別的原因——我只是想知道這是否可能。如果有幫助的話,這是一個可以使用它的虛構(gòu)情況:想象一種類型Enum用作只讀數(shù)據(jù)源,這樣每個值都Enum包含不同的內(nèi)容。器物。Enum_ Readable現(xiàn)在,假設我們需要一個將 的所有值讀取Enum到單個緩沖區(qū)中的方法。這可以作為輔助類中的靜態(tài)實用方法來實現(xiàn)(見下文)。public class ReadableEnumUtils {    /** reads data from all enum values into the charbuffer */    public static <T extends Enum<T> & Readable> int readAll(Class<T> clazz, CharBuffer cb) throws IOException {        int total = 0;        for (T e : clazz.getEnumConstants()) {            int intermediate = e.read(cb);            if (intermediate < 0) {                throw new IllegalArgumentException("The enum value \'" + e.name() + "\' had no data to read.");            }            total += intermediate;        }        return total;    }}最好在接口中聲明該方法,但這可能會造成混淆,因為非 Enum 類不應實現(xiàn)此類方法并不是立即顯而易見的。理想情況下,接口的定義方式可以使編譯器確保它僅由 的子類實現(xiàn)Enum。以下是該界面的示例:interface ReadableEnum extends Readable {    int read(CharBuffer cb) throws IOException;    int readAll(CharBuffer cb) throws IOException;}我認為不可能讓編譯器確保ReadableEnum僅由子類實現(xiàn)Enum- 這是正確的嗎?
查看完整描述

2 回答

?
慕森卡

TA貢獻1806條經(jīng)驗 獲得超8個贊

Java 默認情況下不支持類似的功能,您會問為什么不提供規(guī)范鏈接,但沒有特殊原因,只是沒有人決定添加這樣的功能,您可以自己提出 - 但隨后您可能會了解到它們不認為這是需要的,并且不會將其添加到語言中。


但是java提供了非常強大的選項來自行實現(xiàn)這一點:注釋處理。

我創(chuàng)建了帶有注釋的簡單 java 8 maven 項目:


@Target(ElementType.TYPE)

@Retention(RetentionPolicy.CLASS)

public @interface EnumInterface {}

并配有特殊處理器


import javax.annotation.processing.*;

import javax.lang.model.SourceVersion;

import javax.lang.model.element.*;

import javax.lang.model.type.*;

import javax.lang.model.util.Types;

import javax.tools.Diagnostic;

import java.util.*;


@SupportedAnnotationTypes("com.gotofinal.enuminterface.EnumInterface")

@SupportedSourceVersion(SourceVersion.RELEASE_8)

public class EnumInterfaceProcessor extends AbstractProcessor {

    @Override

    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

        Messager messager = processingEnv.getMessager();

        Types typeUtils = processingEnv.getTypeUtils();


        // first we scan for all interfaces marked with this annotation

        List<TypeElement> enumOnlyInterfaces = new ArrayList<>();

        for (Element rootElement : roundEnv.getRootElements()) { // getRootElements should return all types being compiled

            if (! (rootElement instanceof TypeElement)) {

                continue;

            }

            TypeMirror typeMirror = rootElement.asType();

            // we check if this class have our annotation, we could also here check if this is an interface (by checking if it does not extend Object directly) and throw error otherwise

            if (rootElement.getAnnotation(EnumInterface.class) != null) {

                enumOnlyInterfaces.add((TypeElement) rootElement);

            }

        }


        // and now we scan for any non enum types that implement this interface

        for (Element rootElement : roundEnv.getRootElements()) {

            if (! (rootElement instanceof TypeElement)) {

                continue;

            }

            TypeElement type = findImplementedInterface(rootElement.asType(), enumOnlyInterfaces, typeUtils);

            if (type == null) {

                continue;

            }

            if (! (rootElement.asType() instanceof DeclaredType)) {

                continue;

            }


            // it's fine if it is an enum

            if (this.isEnum(rootElement.asType(), typeUtils)) {

                continue;

            }


            // and we print error to compiler

            messager.printMessage(Diagnostic.Kind.ERROR, "Interface " + type.getQualifiedName()

                                                                 + " can't be used on non enum class: " + ((TypeElement) rootElement).getQualifiedName());

        }

        return false;

    }


    public TypeElement findImplementedInterface(TypeMirror type, List<TypeElement> interfaces, Types types) {

        for (TypeElement anInterface : interfaces) {

            // types.isSubtype(typeA, typeA) would return true, so we need to add this equals check

            if (!anInterface.asType().equals(type) && types.isSubtype(type, anInterface.asType())) {

                return anInterface;

            }

        }

        return null;

    }


    // maybe there is better way to do this... but I just scan recursively for a subtype with java.lang.Enum name, so it's not perfect but should be enough.

    public boolean isEnum(TypeMirror type, Types types) {

        for (TypeMirror directSupertype : types.directSupertypes(type)) {

            TypeElement element = (TypeElement) ((DeclaredType) directSupertype).asElement();

            if (element.getQualifiedName().contentEquals("java.lang.Enum")) {

                return true;

            }

            if (isEnum(directSupertype, types)) {

                return true;

            }

        }

        return false;

    }

}

并將其注冊到META-INF/services/javax.annotation.processing.Processor文件中:


com.gotofinal.enuminterface.EnumInterfaceProcessor

這段代碼可能可以改進很多,我以前從未編寫過任何注釋處理器。但是當我們創(chuàng)建另一個 Maven 項目并將其聲明為依賴項并編寫如下代碼時:


@EnumInterface

interface TestInterface {}


enum TestEnum implements TestInterface {}


class TestClass implements TestInterface {}

我們將無法編譯它并出現(xiàn)錯誤:


接口 com.gotofinal.enuminterface.TestInterface 不能用于非枚舉類:com.gotofinal.enuminterface.TestClass


查看完整回答
反對 回復 2023-11-10
?
胡子哥哥

TA貢獻1825條經(jīng)驗 獲得超6個贊

如果接口的所有實現(xiàn)都擴展某個類,則該接口的所有實例也是該類的實例;因此,此接口還必須擴展此類。

由于接口聲明的 extends 子句中的每個類型都必須是接口類型,因此您不能使接口擴展Enum?;因此,您無法阻止非枚舉類實現(xiàn)您的接口。

您甚至無法通過替換來實現(xiàn)它,interface ReadableEnum extends Enum因為abstract class ReadableEnum extends Enum枚舉類型不得聲明抽象。


但是您仍然可以通過使其擴展由所有公共方法組成的接口來使其更難實現(xiàn)ReadableEnum非枚舉類:IEnumEnum

public interface IEnum<E extends Enum<E>> extends Comparable<E> {

? ? String name();

? ? int ordinal();

? ? Class<E> getDeclaringClass();

}

interface ReadableEnum<E extends Enum<E> & ReadableEnum<E>> extends Readable, IEnum<E> {

? ? int read(CharBuffer cb) throws IOException;


? ? default int readAll(CharBuffer cb) throws IOException {

? ? ? ? return ReadableEnumUtils.readAll(getDeclaringClass(), cb);

? ? }

}

現(xiàn)在枚舉可以ReadableEnum只通過實現(xiàn)read方法來實現(xiàn),而其他類也必須實現(xiàn)name、ordinal、getDeclaringClass和compareTo。


查看完整回答
反對 回復 2023-11-10
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號