【问题标题】:Java Generics and Static Factory Methods -- SyntaxJava 泛型和静态工厂方法——语法
【发布时间】:2014-01-12 03:55:30
【问题描述】:

这是我得到的:

public class Node<T> {

    // instance variables
    private Node<T> next;
    private T data;

    // construct with data
    private Node(T data){
        next = null;
        this.data = data;
    }

    // construct without data
    private Node(){
        next = null;
        this.data = null;
    }

    // static factory method
    public static <T> Node<T> newNodeWithData(T data){
        return new Node<T>(data);
    }

    // static factory method
    public static <T> Node<T> newNode(){
        return new Node<T>();
    }
...
}

我的问题实际上只是关于泛型的语法以及静态工厂方法的语法。我不太明白为什么我们在方法声明中将 放在返回类型之前。是不是有点像类型转换?任何帮助将不胜感激!

【问题讨论】:

    标签: java generics syntax static factory


    【解决方案1】:

    您要问的是类型推断

    由于它是一个静态方法,它必须从某个地方推断出 Generic 类型;您没有该类的实例。这就是&lt;T&gt; 的含义。

    在你的方法不带参数的情况下,它实际上是从赋值的目标中推断出来的。例如,假设您的方法如下所示:

    public static <T> List<T> getNewList() {
        return new ArrayList<T>();
    }
    

    使用此方法时,T 是从目标推断出来的(在本例中为 String):

    List<String> myList = MyClass.getNewList();
    

    在您具有通用参数的其他静态方法中,T 是从传入的类型推断出来的:

    public static <T> List<T> getNewListWithElement(T element) {
        List<T> list = new ArrayList<T>();
        list.add(element);
        return list;
    }
    

    在这里,如果您尝试这样做:

    List<String> myList = MyClass.getNewListWithElement(new Integer(4));
    

    它会告诉你你的目标类型错误,你需要一个List&lt;Integer&gt;

    JLS 的 15.12.2.715.12.2.8 部分特别介绍了这一点。

    【讨论】:

      【解决方案2】:

      你必须用这种糖装饰静态方法的原因是,作为一个静态方法,它没有从类的声明中继承T

      你也可以这样做:

      // static factory methods
      public static <Q> Node<Q> newNode(){
          return new Node<Q>();
      }
      
      public static Node<String> newStringNode(String s){
          return new Node<String>(s);
      }
      

      对声明的简单叙述可能会有所帮助:

      // This static method would have a <T> parameter to the class if it was not static
      public static <T> 
      // It returns an object of type `Node` with generic parameter T
      Node<T> newNode(){
          // And here it is doing it's business.
          return new Node<T>();
      }
      

      【讨论】:

        【解决方案3】:

        这是对静态方法进行参数化的唯一方法,因为 Node 声明中的原始 T 绑定到 Node 的实例字段和方法。所以你可以写:

        public static <T1> Node<T1> newNode(){
            return new Node<T1>();
        }
        

        原始的T 绑定到Node 类的实例,不能在静态上下文中引用。这会导致编译错误:

        // ERROR
        public static Node<T> newNode(){
            return new Node<T>();
        }
        

        【讨论】:

          【解决方案4】:

          &lt;T&gt; 只是一个信号,这个方法使用T 作为类型变量。没有它,编译器会认为Tclassinterfaceenum,它在某处声明并输出错误。它与第一行中使用的 T 不同。你可以把这个方法中的T换成其他字母,或许有助于理解。

          【讨论】:

            【解决方案5】:

            从参数推断出的T

            public static <T> List<T> getNewListWithElement(T element)
            

            编译器如何区分 T 作为类和 T 作为泛型参数?解决方案是使用指定 T 元素是泛型而不是类/接口。

            T 从使用情况推断

            public static <T1> Node<T1> newNode(){
                return new Node<T1>();
            }
            

            如果不做声明,方法体内的T1是谁?

            【讨论】:

              猜你喜欢
              • 2011-01-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-16
              • 1970-01-01
              • 2021-07-26
              • 2011-12-20
              • 2012-12-04
              相关资源
              最近更新 更多