理解java泛型中的一些概念

时间:2017-04-01 07:22:42

标签: java generics

所以我在研究链表时遇到了这段代码。这里的代码使用泛型,我在解决这里的一些问题时遇到了问题。

public static class Node<E> 
{
     E element;
     Node <E> next;
    public Node(E e,Node <E> n)
    {
        element=e;
        next=n;System.out.println(next);
    }
    public E getelement() {return element;}
    public Node<E> getnext(){ return next;}
    public void setnext(Node <E> n)
    {
        next=n;
    }
}

那么类节点<E>是什么意思? 我觉得E元素;意味着元素属于E.我是对的吗? 接下来是节点<E>;这是什么意思?

3 个答案:

答案 0 :(得分:0)

类名<E>声明E为泛型类型参数 - 这意味着Node的任何实例都属于某种类型,这种类型将由实例化它的代码。 new Node<String>()将创建一个String类型的节点,new Node<Integer>()创建一个Integer类型的节点,依此类推。

在类中使用E然后反映特定实例所选择的任何类型,因此如果a具有String类型的节点,我知道element将是一个String,并且{{ 1}}将是对包含String的另一个节点的引用。

泛型的美妙之处在于使用此类型参数意味着我不需要为我想要使用的每种类型编写此类的副本,同时还要确保所有引用都是我期望的类型 - 当我期待一个字符串时,我不会让next返回一个整数。

documentation非常好 - 泛型是一个非常大而微妙的主题,如果你想了解泛型,那么教程会对你有很大的帮助。

答案 1 :(得分:0)

您可以轻松地找到official docs以及许多其他资源来解决Java中这样一个大问题,我将尝试通过重新创建泛型的过程来解释它。&#34;。< / p>

假设您要实现问题中给出的类Node,它是LinkedList的基本构建单元,因此您将其定义为:

class Node {
    private Node next;

    public Node getNext() {
        return next;
    }

    public void setNext(Node n) {
        next = n;
    }
}

但你需要在每个Node中存储一些数据,不要这样做,否则这个类就没用了。显然,还需要一个字段,您要存储的类型为MyData,然后它将是:

class Node {
    private MyData element;
    private Node next;

    public Node getNext() {
        return next;
    }

    public MyData getElement() {
        return element;
    }

    public void setElement(MyData element) {
        this.element = element;
    }

    public void setNext(Node n) {
        next = n;
    }
}

有一天,您希望将您的实施设置为一个公共库,以便任何人都可以使用它,但是会出现一个严重的问题,即人们不会满意他们只能将MyData类型的数据存储在您的Node,他们希望存储他们想要的任何类型,因此您进行了一些更改 - 将element的类型声明为Object,以便它可以处理任何类型:

class Node {
    private Object element;
    private Node next;

    public Node getNext() {
        return next;
    }

    public Object getElement() {
        return element;
    }

    public void setElement(Object element) {
        this.element = element;
    }

    public void setNext(Node n) {
        next = n;
    }
}

现在一切都很好,但过了一段时间后你会收到一些挑剔用户的反馈意见:

  • 用户A:我在我的代码中调用Node.getElement()的所有地方,我得到Object类型的东西,我需要进行类型转换,这很不方便,如果我得到的话会更好getElement是我想要的类型
  • 用户B:我只想存储A类型,但我无法阻止我将B类型添加到Node中,我无法找到这个bug直到在运行时发生异常,编译器可以帮助我找到bug
  • 会更好

所以,如果您可以决定允许type数据被允许放入Node给用户,而不是在实施中硬编码,那么您觉得它会很棒您将在语句private ___ element;的下划线中放置的内容是不确定的,您需要它是一个变量并由用户在使用时指定,因此该类的变量,这很好,但你需要一个地方在你可以使用它之前声明变量,最后你决定把变量的声明放在类名之后,在{ {1}}(一种新语法),然后代码将是:

<>

差不多完成但等待:您自己使用class Node<E> { private E element; private Node next; public E getElement() { return element; } public void setElement(E element) { this.element = element; } public Node getNext() { return next; } public void setNext(Node n) { next = n; } } - 字段Node,您需要遵循刚刚制定的规则:将元素的类型信息传递给{ {1}}当你使用它时,所以最后你得到了以下代码:

next
Em ....对不起,我没想到会这么久......但希望它对你有点帮助。

答案 2 :(得分:0)

我总是从示例中学到最好,所以将Node简单地用于:

import java.awt.Point;

public class TestNode{

    public static void main(String[] args) {

        //assume you have 3 points
        Point point1 = new Point(40,40);
        Point point2 = new Point(80,120);
        Point point3 = new Point(70,200);

        //each point is connected to one other point. to represent such connection you
        //can create a Node<Point> or in other words Node of Point.
        //define the last node in the chain, which has no next node:
        Node<Point> node3 = new Node<>(point3, null);
        //Note: because Node<E> is generic you could define Node<Cats>, Node<Dogs>, Node<AnyType>

        //define the point2-point3 connection
        Node<Point> node2 = new Node<>(point2, node3);
        //define point1-point2 connection
        Node<Point> node1 = new Node<>(point1, node2);

        //now put it to test. node1.getnext() return node2, node1.getnext().getelement() returns point2
        System.out.println("Point 2 x-y " +node1.getnext().getelement().getX()
                                                              +"-"+node1.getnext().getelement().getY());

        //now put it to test. node1.getnext().getnext() return node3
        System.out.println("Point 3 x-y " +node1.getnext().getnext().getelement().getX()
                                                    +"-"+node1.getnext().getnext().getelement().getY());
    }
}