不能实例化类型list

java接口可以实例化吗?

接口不可以实例化。但是接口对象可以指向它的实现类对象。
接口可以看做特殊的抽象类,只是所有的方法都是抽象方法(没有实现的方法),接口的方法都是默认public abstract的,
所以不能被实例化。
比如:
List Set Map都是接口
使用时先实现

List list = new ArrayList<>();

有点类似于指针的感觉了。Factory接口可以用来代表实现它的类。比如:
public interface thing;
public class fruit implements thing;
thing something = new fruit();
这个something指的就是水果。

接口编程是为了实现多继承。

、、、、、、、、、、、、、、、、

以下转自:http://www.runoob.com/java/java-polymorphism.html

声明一个接口的变量(接口的引用)可以指向一个实现类(实现该接口的类)的实例,

但是该接口的变量不能使用实现类中有、接口中没有的方法(实现类中没有重写的方法、自添加的方法),比如:

public class InterfaceCat {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法

Animal a = new Cat();  // 向上转型  

// a.eat(); // 调用的是 Cat 的 eat
// Cat c = (Cat)a; // 向下转型
// c.work(); // 调用的是 Cat 的 catchMouse
a.work(); //该处编译报错
}

public static void show(Animal a)  {
  a.eat();  
    // 类型判断
    if (a instanceof Cat)  {  // 猫做的事情 
        Cat c = (Cat)a;  
        c.work();  
    } else if (a instanceof Dog) { // 狗做的事情 
        Dog c = (Dog)a;  
        c.work();  
    }  
}  

}

abstract class Animal {
abstract void eat();
// abstract void work(); // 抽象类(接口)中没有work方法

}

class Cat extends Animal {
public void eat() {
System.out.println(“吃鱼”);
}
public void work() {
System.out.println(“抓老鼠”);
}
}

class Dog extends Animal {
public void eat() {
System.out.println(“吃骨头”);
}
public void work() {
System.out.println(“看家”);
}
}

输出结果为:

吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠

对于多态,可以总结以下几点:

一、使用父类类型的引用指向子类的对象;

二、该引用只能调用父类中定义的方法和变量;

三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用);

四、变量不能被重写(覆盖),”重写”的概念只针对方法,如果在子类中”重写”了父类中的变量,那么在编译时会报错。

Java中的泛型

泛型就是参数化类型,就是所操作的数据类型被指定为一个参数,这种类型可以在类接口和方法中创建,分别称之为泛型类,泛型接口,泛型方法

泛型类

就是一个或者多个具有类型变量的类;如下:
public class Pair{
private T first;
private T second;
public Pair(){
first = null;
second = null;
}
public void setFirst(T first){
this.first = first;
}
public void setSecond(T second){
this.second = second
}
public T getFirst(){
return this.first;
}
public T getSecond(){
return Second;
}
}
Pair类引入了一个类型变量T,将其放在”<>”里面;并且将其放在类名的后面,泛型类也可以有多个类型变量;
可以将泛型类看做是普通类的工厂;

泛型方法

带有类型参数的简单方法;
泛型方法可以定义在普通类里面也可以定义在泛型类里面;
所谓的泛型方法要么就是返回值是一个泛型,要么就是参数是泛型;
class ArrayAlg{
public static T getMiddle(T[] a){
return a[a.length/2]
}
}

泛型接口

就是一个或者多个具有类型变量的接口
pulbic interface Collection extends Iterable {
Iterator iterator();
}

约束和局限性:

使用java中的泛型时需要考虑一些限制,大多是限制都是由于类型擦除引起的;

<1>:不能用基本类型实例化类型参数
没有Pair只有Pair

<2>:运行时类查询只适用于原始类型
虚拟机中的对象总有一个特定的非泛型类型。因此所有的类型查询只产生原始类型。例如:
if(a instanceof Pair)//ERROR

<3>:不能创建参数化类型的数组:
Pair[] table = new Pair[10]//ERROR;
但是声明类型Pair[]的变量仍是合法的;

<4>:Varargs警告:
由于java布置池泛型类型的数组;当我们向一个参数个数可变的方法 传递一个泛型类型的实例:
eg:

public static void addAll(Collection coll,T…ts){
for(T t:ts)coll.add(t);
}
实际上ts是一个数组,包含提供的所有实参。
Collection<Pair> table = …;
Pair pair1 = ….;
Pair pair2 = ….;
Pair pair3 = ….;
addAll(table,pair1,pair2);
为了调用这个方法,Java虚拟机必须建立一个Pair数组;违反前面的规定;但是这种情况并不会报告错误仅仅会报告一个警告可以通过两种方式去消除它:
A:为addAll方法添加标注@SuppressWarning(“unchecked”).
B:@SafeVarargs直接标志addAll方法
@SafeVarags
public static void addAll(Collection coll,T…ts)

<5>:不能实例化类型参数

new T(…),new T[]或者T.class都是不允许的;
但是可以通过反射加上一定的API便可实现泛型的实例化;
`java
public static Pair makePair(Class cl){
try{
return new Pair<>(cl.newIntance(),cl.newInstance())
}catch(Exception e){
return null;
}
}
Pair p = Pair.makePair(String.class)
类型擦除会让这个方法永远构造Object[2]数组;
如果数组仅仅作为一个类的私有实例域,就可以将这个数组声明为Object[],并在获取元素时进行类型转换。例如ArrayList就是这样实现的;

Public class ArrayList{
Private Object[] elements;
@SuppressWarning(‘unchecked’)
public E get(int n){
return (E) elements[n]}
}
Public void set(int n,E e){elements[n] = e};
Public class ArrayList{
Private E[] elements;
Public ArrayList(){
Elements = (E[])new Object[10];//假像:类型擦除会使其无法差距
}
}
编译时不会报错,但是当我们的程序执行时,当我们把Object[]引用赋值给T[]时就会报错;将会发生ClassCastException异常;
这种情况下我们可以利用反射:

Public static T[] minmax(T…a){
T[] mm = (T[])Array.newInstance(a.getClass().getComponentType(),2)
}

<6>泛型类的静态上下文中类型变量无效
不能在静态域或方法中引用类型变量(即泛型);(即被static修饰的域或者方法)

<7>:不能抛出或者捕获泛型类的实例
既不能抛出也不能捕获泛型类的实例对象。实际上,甚至泛型类扩展Throwable都是不合法的;T extends Exception(Throwable)
Catch字句中不能使用类型变量;catch(T e)Error;
PS:可以消除已检查异常的检查:
Java异常处理的一个基本原则:必须为所有的已检查异常提供一个处理器;不过可以利用泛型消除这个限制;
当你必须捕获run中所有的已检查异常,将其包装到未检查异常中,因为run方法声明为不抛出任何已检查异常;
不过在这里我么你没有选择这种“包装”我们只是抛出异常,并“哄骗浏览器”让它认为这不会一个已检查异常;
通过使用泛型类,擦除,和@SuppertWarning标注就可以消除java类型系统的部分限制

<8>注意擦除后的冲突:
当泛型类型被擦除时,无法创建引发冲突的条件,如:
在某个泛型类中添加equals()方法,当我们给这个泛型类中间穿具体的类型时:
进过类型擦除之后equals(String o)方法变为equals(Object o);
所以此时从概念上讲:他有两个equals方法:
Boolean equals(String)
Boolean equals(Object)和Object.Equals(Object)方法冲突;
补救方法就是重命名引发错误的方法
另外一个原则:“想要支持擦除的转换,就需要强行限制一个类或类型变量不能同时成为两个接口类型的子类”而这两个接口是同一个接口的不同参数化;
例如下面的代码就是非法的

Class Calendar implements Comparable{…}
Class GregorianCalendar extends Calendar implements Comparable< GregorianCalendar>(Error)
GregorianCalendar会事先Comparable和Comparable
这是同一接口的不同参数化;这一限制和类型擦柱的关系不是十分明确;下列的非泛型的版本就是合法的;
原因:有可能与合成的桥方法产生冲突。实现了Comparable的类可以获得一个桥方法;

Public int comparaTo(Object other){
return compareTo(X) other
};
对于不同类型的;不能有两个这样的方法;

<9>泛型类型的继承规则:
例如:Employee和Manager。Pair和Pair之间没有任何关系;
无论S和T有什么关系,通常Pair和Pair之间都不会有什么联系;
继承泛型类
子类不是泛型类:需要给父类传递类型常量
当给父类传递的类型常量为String时,那么在父类中所有T都会被String替换!

子类是泛型类:可以给父类传递类型常量,也可以传递类型变量

参考自:https://www.jianshu.com/p/fa66f06b701b