Java内部类与外围类泛型参数

Java内部类与外围类泛型参数

在Java的编程中,经常使用常规内部类和静态内部类(即嵌套类),当外围类和内部类都是用泛型参数时,会存在一些需要注意的问题。

问题的起源

LinkedList的Java实现:

import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyLinkedList<T> implements Iterable<T> {

    // 静态内部类,定义节点结构
    private static class Node<T> {
        private T data;
        private Node<T> prev;
        private Node<T> next;

        public Node(T data,Node<T> prev,Node<T> next) {
            this.data=data;
            this.prev=prev;
            this.next=next;
        }
    }

    private int size;
    private int modCount=0;
    private Node<T> begin;
    private Node<T> end;

    /*一些方法实现
    *clear()
    *size()
    *isEmpty()
    *add(T x)
    *add(int index, T x)
    *get(int index)
    *remove(int index)
    */

    public MyLinkedList() {
        // TODO Auto-generated constructor stub
    //  clear();
    }


    @Override
    public Iterator<T> iterator() {
        // TODO Auto-generated method stub
        return new LinkedListIterator();
    }

    // 非静态内部迭代类
    private class LinkedListIterator implements Iterator<T> {

        private Node<T> current=begin.next;
        private int expectedModCount=modCount;
        private boolean okToRemove=false;

        /*一些方法实现
        *hasNext()
        *next()
        *remove()
        */


    }


}

泛型类实现泛型接口

  • 泛型类声明的泛型参数占主导地位,如泛型类声明的参数为<T>,则泛型接口的泛型参数也应为<T>
  • 当泛型类声明的参数为<T>时,泛型接口的参数<T>可以不写;
  • 当泛型接口的参数为<T>时,潜在表明泛型类的参数为<T>,必须在泛型类中声明<T>
// 规范写法
public class MyClass1<T> implements Iterator<T> {

    @Override
    public boolean hasNext() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public T next() {
        // TODO Auto-generated method stub
        return null;
    }

}
// 不规范写法
public class MyClass1<T> implements Iterator {

    /* implementaion */

}
// 错误写法: T cannot be resolved to a type
public class MyClass1 implements Iterator<T> {

    /* implementaion */

}

非静态内部类会自动继承外围类泛型参数

LinkedList实现中:存在一个静态内部类private static class Node<T>,一个非静态内部类LinkedListIterator,并且该非静态内部类实现了Iterator<T>

按照规范写法,LinkedListIterator的形式应当是在LinkedListIterator中声明泛型参数<T>,如下所示。

private class LinkedListIterator<T> implements Iterator<T> {

    private Node<T> current=begin.next;
    private int expectedModCount=modCount;
    private boolean okToRemove=false;

    /* implementaion */
}

但这样private Node<T> current=begin.next;就会报错,类型不匹配,
Type mismatch: cannot convert from MyLinkedList.Node to MyLinkedList.Node

经过Google一番得知,对于非静态内部类,会自动继承外围类的泛型参数,即LinkedListIterator已经有默认的泛型参数<T>,而这里又重新声明一个新的泛型参数<T>,两者并不相同。

结论:对于非静态内部类,无需再次声明泛型参数

静态内部类不会自动继承外围类泛型参数

事实上,Node<T>中的泛型参数<T>MyLinkedList<T>中的<T>没有任何联系,只是这里使用相同的符号T而已。

一些测试

对内部类和外围类的泛型参数之间的关系进行一些测试

import java.util.Iterator;

public class GenericType<T> {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        GenericType<Integer> a=new GenericType<>(new Integer(5));
        MyClass<Integer> b=new MyClass<>(a.getX());

        MyClass2<Integer> c=new MyClass2<>();
    }

    private T x;

    public GenericType(T x) {
        // TODO Auto-generated constructor stub
        this.x=x;
    }

    public GenericType() {
        // TODO Auto-generated constructor stub

    }


    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }



    // 非静态内部类会自动继承外部类的泛型
    // 这里又重新声明了一个新的泛型<T>
    // Inner1<T>中声明的<T>与Demo11<T>中的<T>不同
    // 导致T y=x;报错:Type mismatch: cannot convert from T to T
    private class Inner1<T> {
//      T y=x;
    }

    private class Inner5<K> {
//      K y=x; // Type mismatch: cannot convert from T to K
    }

    // 需去掉<T>
    private class Inner2 {
        T y=x;
    }

    // 需去掉<T>,接口应写为<T>
    private class Inner6 implements MyInterface<T> {
        T y=x;
    }

    // 接口写为其他,如<E>均报错
//  private class Inner7 implements MyInterface<E> {
//      E y; // E cannot be resolved to a type
//  }

    // 静态内部类不会自动继承外部类的泛型,相当于独立于外部类
    // 可以自己声明泛型
    private static class Inner3<T> {
        T z=new GenericType<T>().x;
    }

    // 可以自己声明泛型,并且不需要和外部类的泛型声明相同
    private static class Inner4<V> {
        V v=new GenericType<V>().x; 
    }

}


interface MyInterface<E> {

}

class MyClass<R> {
    private R r;
    public MyClass(R r) {
        // TODO Auto-generated constructor stub
        this.r=r;
    }
}


class MyClass1<T> implements Iterator<T> {

    @Override
    public boolean hasNext() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public T next() {
        // TODO Auto-generated method stub
        return null;
    }

    /* implementation */

}


class MyClass2<V> implements Iterator {

    @Override
    public boolean hasNext() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Object next() {
        // TODO Auto-generated method stub
        return null;
    }

}

刚学编程不久,欢迎大家探讨交流!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值