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

来源:互联网 发布:安顺浪人网络官网 编辑:程序博客网 时间:2024/05/30 04:48

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 typepublic 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;    }}

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

0 0