匿名類作為泛型參數 (anonymous class as generic parameter)


問題描述

匿名類作為泛型參數 (anonymous class as generic parameter)


我想創建一個從匿名類定義中獲取對象的類來存儲。我使用了一個泛型類型的類來實現這一點。然後我想使用功能接口定義一些操作,這些接口將這個對像作為參數來使用。
代碼比文字更重要。所以看看這個:

public class Test<T> {
    @FunctionalInterface
    public interface operation<T> {
        void execute(T object);
    }
    private T obj;
    public Test(T _obj){
        obj = _obj;
    }
    public void runOperation(operation<T> op){
        op.execute(obj);
    }

    public static void main(String[] args){
        Test<?> t = new Test<>(new Object(){
            public String text = "Something";
        });
        t.runOperation((o) ‑> {
            System.out.println(o.text);  // text cannot be resolved
        });
    }
}

我的問題是在功能接口的實現中o.text無法解決。這是某種類型擦除的後果嗎?
有趣的是,當我在構造函數中實現功能接口時,我可以讓這段代碼工作。
看看這段代碼:

public class Test<T> {
    @FunctionalInterface
    public interface operation<T> {
        void execute(T object);
    }
    private T obj;
    private operation<T> op;

    public Test(T _obj, operation<T> _op){
        obj = _obj;
        op = _op;
    }
    public void runOperation(){
        op.execute(obj);
    }
    public static void main(String[] args){
        Test<?> t = new Test<>(new Object(){
            public String text = "Something";
        }, (o) ‑> {
            System.out.println(o.text);
        });
        t.runOperation();
    }
}

這很完美,可以打印出“某事”。但是我的第一種方法有什麼問題?我真的不明白這裡的問題。


參考解法

方法 1:

The problem is that your anonymous class still has to conform to (extend or implement) some type, and the type you've chosen is Object which doesn't have your text property. In order to refer to properties of some kind, you'll need an actual class or interface to work with, so the compiler can make guarantees about what properties and methods are available on the object.

This works.

public class Test<T> {

    public static class Data {
        public String text;
    }

    @FunctionalInterface
    public interface Operation<K> {
        void execute(K object);
    }

    private T obj;
    private Operation<T> op;

    public Test(T obj) {
        this.obj = obj;
    }

    public void runOperation(Operation<T> op) {
        op.execute(obj);
    }

    public static void main(String[] args) {
        Test<Data> t = new Test<>(new Data() {{
            this.text = "Something";
        }});

        t.runOperation((o) ‑> {
            System.out.println(o.text);
        });
    }
}

方法 2:

  Test<?> t = new Test<>(new Object(){
            public String text = "Something";
        }, (o) ‑> {
            System.out.println(o.text);
        });

The compiler here is replacing T in Test with your anonymous class and since that class contains a variable text that's why the 2nd case works.

方法 3:

In the second piece of code,

    new Test<>(new Object(){
        public String text = "Something";
    }, (o) ‑> {
        System.out.println(o.text);
    });

compiles because the type argument of Test for the constructor call is inferred (since the diamond operator is used), and it is inferred to the anonymous type that the first argument evaluates to (the anonymous class type), and thus the second argument's type is operation<that anonymous class type>, which works.

In the first piece of code, the expression

    t.runOperation((o) ‑> {
        System.out.println(o.text);  // text cannot be resolved
    })

does not compile. Here, the type of the lambda is inferred based on the type of the variable t, which is Test<?>. Thus, the argument of runOperation must be operation<some unknown type>. The only argument to runOperation that will work here is null.

(by ArcticLordIan McLairdRamanlfcnewacct)

參考文件

  1. anonymous class as generic parameter (CC BY‑SA 2.5/3.0/4.0)

#lambda #anonymous-class #java #generics






相關問題

Lambda 表達式中的 SQL WHERE 等價物是什麼? (What's the equivalence of an SQL WHERE in Lambda expressions?)

如何將 lambda 傳遞給 Razor 輔助方法? (How to pass in a lambda to a Razor helper method?)

lỗi biểu thức lambda: biểu thức phải là giá trị có thể sửa đổi (lambda expression error: expression must be a modifiable lvalue)

如何在 PySpark 中有效地按值排序? (How to sort by value efficiently in PySpark?)

將列表列表減少為字典,以子列表大小為鍵,出現次數為值 (Reduce list of list to dictionary with sublist size as keys and number of occurances as value)

匿名類作為泛型參數 (anonymous class as generic parameter)

如何為 lambda 中的運算符賦予不定性? (How to give infixities to operators in lambda?)

如何發出委託或 lambda 表達式 (Howto emit a delegate or lambda expression)

深入學習 C# 表達式樹的最佳資源是什麼? (What is the best resource for learning C# expression trees in depth?)

根據最高日期從 IGrouping 中獲取項目 (Get an item from a IGrouping based on the highest date)

如何在 C# 中使用“param”來獲取這個示例? (How can I get this example using "param" in C# to work?)

如何使用 C# 中的 Lambda 表達式僅返回沒有來自另一個表的行的行 (How to return only rows where no rows from another table using Lambda Expressions in C#)







留言討論