内部类内部的静态类不能转换 [英] Inner static class inside inner class cannot be converted

查看:158
本文介绍了内部类内部的静态类不能转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个问题中受到启发:如何实现Iterable 我决定做一个基本的链表实现并在其中实现一个迭代器为了得到这样的代码:

  MyList< String> myList = new MyList< String>(); 
myList.add(hello);
myList.add(world);
for(String s:myList){
System.out.println(s);
}

代码不难处理,创建一个 class MyList< T>使用 private static class Node< T> 和a private class MyListIterator< T>实现Iterable< T>实现Iterator< T> ,但是当我实现我自己的版本的 Iterator#remove 时遇到了问题:

  class MyList< T>实现了Iterable< T> {
private static class Node< T> {
//基本节点实现...
}
私有节点< T>头;
私人节点< T>尾巴;
//构造函数,添加方法...
private class MyListIterator< T>实现Iterator< T> {
私人节点< T> headItr;
私人节点< T> prevItr;
public MyListIterator(Node< T> headItr){
this.headItr = headItr;
}
@Override
public void remove(){
//下面的行编译
if(head == headItr){
// line below编译
head = head.getNext();
//下面的行不会给我消息
//类型不匹配:无法从another.main.MyList.Node< T>转换为
//another.main。 MyList.Node< T>中
head = headItr.getNext();
//下面的行不能编译,仅用于测试目的(它将被删除)
head = headItr;
}
}
}
}

错误信息引发了我的好奇心。我在网上查找这个问题,但没有发现任何东西(或者我可能不擅长搜索这类问题)。这是什么原因,从相同类型的两个变量进行比较,但不能分配给对方?



顺便说一句,我知道我可以看看代码 LinkedList ,并检查Java设计者如何实现这一点,并将其复制/粘贴/适配到我自己的实现中,但我更愿意解释和理解真正的问题。



完整的代码显示了我当前实现的 MyList class:

  class MyList< T>实现了Iterable< T> {
private static class Node< T> {
私人T数据;
私人节点< T>下一个;
public Node(T data){
super();
this.data = data;
}
public T getData(){
返回数据;
}
公共节点< T> getNext(){
next next;
}
public void setNext(Node< T> next){
this.next = next;
}
}
私人节点< T>头;
私人节点< T>尾巴;
private int size;
public MyList(){
head = null;
tail = null;
}
public void add(T data){
Node< T> node = new Node< T>(data);
if(head == null){
head = node;
tail = head;
} else {
tail.setNext(node);
tail = node;
}
size ++;
}
private class MyListIterator< T>实现Iterator< T> {
私人节点< T> headItr;
私人节点< T> prevItr;
public MyListIterator(Node< T> headItr){
this.headItr = headItr;

@Override
public boolean hasNext(){
return(headItr.getNext()!= null);


@Override
public T next(){
T data = headItr.getData();
prevItr = headItr;
if(hasNext()){
headItr = headItr.getNext();
}
返回数据;
}

@Override
public void remove(){
if(head == headItr){
//这里有问题
头= headItr.getNext();
}
//实现仍在开发中...
}
}
@Override
public Iterator< T> iterator(){
return new MyListIterator< T>(head);


$ / code>


解决方案

是问题:

  class MyList< T>实现了Iterable< T> {
private class MyListIterator< T>实现Iterator< T> {
...
}
}

在你的减价版本中,你无法帮助 MyList 非泛型。)



有两个不同的 T 类型变量 - 嵌套类和外部类中的一个。你不需要 Node 是通用的 - 你只需要:

  class MyList< T>实现了Iterable< T> {
private class MyListIterator实现Iterator< T> {
...
}
}

现在只有 T - 外部类中的一个。这不像你希望列表迭代器从封闭实例中声明的那个 T >,所以你不希望它是另一种方式:尝试在名称不同的类型参数中使用 MyListIterator 泛型,然后它会变得更清晰,因为这两个名字在错误信息中是可区分的。它是有效的:

 类型不匹配:无法从another.main.MyList.Node转换< TOuter> to 
another.main.MyList.Node< TInner>

(反之亦然)。


Inspired in this question: How to implements Iterable I decided to make a basic linked list implementation and implement an iterator in order to have a code like this:

MyList<String> myList = new MyList<String>();
myList.add("hello");
myList.add("world");
for(String s : myList) {
    System.out.println(s);
}

The code wasn't hard to deal with, creating a class MyList<T> implements Iterable<T> with a private static class Node<T> and a private class MyListIterator<T> implements Iterator<T>, but then I came across a problem when implementing my own version of Iterator#remove:

class MyList<T> implements Iterable<T> {
    private static class Node<T> {
        //basic node implementation...
    }
    private Node<T> head;
    private Node<T> tail;
    //constructor, add methods...
    private class MyListIterator<T> implements Iterator<T> {
        private Node<T> headItr;
        private Node<T> prevItr;
        public MyListIterator(Node<T> headItr) {
            this.headItr = headItr;
        }
        @Override
        public void remove() {
            //line below compiles
            if (head == headItr) {
                //line below compiles
                head = head.getNext();
                //line below doesn't and gives me the message
                //"Type mismatch: cannot convert from another.main.MyList.Node<T> to
                //another.main.MyList.Node<T>"
                head = headItr.getNext();
                //line below doesn't compile, just for testing purposes (it will be deleted)
                head = headItr;
            }
        }
    }
}

This error message raised my curiosity. I was looking on the net about this problem but found nothing (or probably I'm not so good at searching this kind of issues). What would be the reason of two variables from the same type being compared but not being assignable to each other?

By the way, I know that I can just look at the code of LinkedList and check how the Java designers implemented this and copy/paste/adapt it to my own implementation, but I prefer to have an explanation and understanding of the real problem.

Complete code that shows my current implementation of MyList class:

class MyList<T> implements Iterable<T> {
    private static class Node<T> {
        private T data;
        private Node<T> next;
        public Node(T data) {
            super();
            this.data = data;
        }
        public T getData() {
            return data;
        }
        public Node<T> getNext() {
            return next;
        }
        public void setNext(Node<T> next) {
            this.next = next;
        }
    }
    private Node<T> head;
    private Node<T> tail;
    private int size;
    public MyList() {
        head = null;
        tail = null;
    }
    public void add(T data) {
        Node<T> node = new Node<T>(data);
        if (head == null) {
            head = node;
            tail = head;
        } else {
            tail.setNext(node);
            tail = node;
        }
        size++;
    }
    private class MyListIterator<T> implements Iterator<T> {
        private Node<T> headItr;
        private Node<T> prevItr;
        public MyListIterator(Node<T> headItr) {
            this.headItr = headItr;
        }
        @Override
        public boolean hasNext() {
            return (headItr.getNext() != null);
        }

        @Override
        public T next() {
            T data = headItr.getData();
            prevItr = headItr;
            if (hasNext()) {
                headItr = headItr.getNext();
            }
            return data;
        }

        @Override
        public void remove() {
            if (head == headItr) {
                //problem here
                head = headItr.getNext();
            }
            //implementation still under development...
        }
    }
    @Override
    public Iterator<T> iterator() {
        return new MyListIterator<T>(head);
    }
}

解决方案

This is the problem:

class MyList<T> implements Iterable<T> {
    private class MyListIterator<T> implements Iterator<T> {
        ...
    }
}

(It doesn't help that in your cut down version you've made MyList non-generic.)

At that point there are two different T type variables - the one in the nested class and the one in the outer class. You don't need Node to be generic - you just need:

class MyList<T> implements Iterable<T> {
    private class MyListIterator implements Iterator<T> {
        ...
    }
}

Now there's only one T - the one in the outer class. It's not like you want the list iterator to have a different T from the one declared in the enclosing instance, so you don't want it to be generic.

To put it another way: try making MyListIterator generic in a type parameter with a different name, and then it'll be clearer what's going wrong, as the two names will be distinguishable in the error message. It's effectively:

Type mismatch: cannot convert from another.main.MyList.Node<TOuter> to
another.main.MyList.Node<TInner>

(or vice versa).

这篇关于内部类内部的静态类不能转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆