java接口可以实例化吗?
接口不可以实例化。但是接口对象可以指向它的实现类对象。
接口可以看做特殊的抽象类,只是所有的方法都是抽象方法(没有实现的方法),接口的方法都是默认public abstract的,
所以不能被实例化。
比如:
List Set Map都是接口
使用时先实现
List
有点类似于指针的感觉了。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
return a[a.length/2]
}
}
泛型接口
就是一个或者多个具有类型变量的接口
pulbic interface Collection
Iterator
}
约束和局限性:
使用java中的泛型时需要考虑一些限制,大多是限制都是由于类型擦除引起的;
<1>:不能用基本类型实例化类型参数
没有Pair
<2>:运行时类查询只适用于原始类型
虚拟机中的对象总有一个特定的非泛型类型。因此所有的类型查询只产生原始类型。例如:
if(a instanceof Pair
<3>:不能创建参数化类型的数组:
Pair
但是声明类型Pair
<4>:Varargs警告:
由于java布置池泛型类型的数组;当我们向一个参数个数可变的方法 传递一个泛型类型的实例:
eg:4>
public static
for(T t:ts)coll.add(t);
}
实际上ts是一个数组,包含提供的所有实参。
Collection<Pair
Pair
Pair
Pair
addAll(table,pair1,pair2);
为了调用这个方法,Java虚拟机必须建立一个Pair
A:为addAll方法添加标注@SuppressWarning(“unchecked”).
B:@SafeVarargs直接标志addAll方法
@SafeVarags
public static
<5>:不能实例化类型参数5>
new T(…),new T[]或者T.class都是不允许的;
但是可以通过反射加上一定的API便可实现泛型的实例化;`
java
public static
try{
return new Pair<>(cl.newIntance(),cl.newInstance())
}catch(Exception e){
return null;
}
}
Pair
类型擦除会让这个方法永远构造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[] mm = (T[])Array.newInstance(a.getClass().getComponentType(),2)
}
<6>泛型类的静态上下文中类型变量无效
不能在静态域或方法中引用类型变量(即泛型);(即被static修饰的域或者方法)6>
<7>:不能抛出或者捕获泛型类的实例
既不能抛出也不能捕获泛型类的实例对象。实际上,甚至泛型类扩展Throwable都是不合法的;T extends Exception(Throwable)
Catch字句中不能使用类型变量;catch(T e)Error;
PS:可以消除已检查异常的检查:
Java异常处理的一个基本原则:必须为所有的已检查异常提供一个处理器;不过可以利用泛型消除这个限制;
当你必须捕获run中所有的已检查异常,将其包装到未检查异常中,因为run方法声明为不抛出任何已检查异常;
不过在这里我么你没有选择这种“包装”我们只是抛出异常,并“哄骗浏览器”让它认为这不会一个已检查异常;
通过使用泛型类,擦除,和@SuppertWarning标注就可以消除java类型系统的部分限制7>
<8>注意擦除后的冲突:
当泛型类型被擦除时,无法创建引发冲突的条件,如:
在某个泛型类中添加equals()方法,当我们给这个泛型类中间穿具体的类型时:
进过类型擦除之后equals(String o)方法变为equals(Object o);
所以此时从概念上讲:他有两个equals方法:
Boolean equals(String)
Boolean equals(Object)和Object.Equals(Object)方法冲突;
补救方法就是重命名引发错误的方法
另外一个原则:“想要支持擦除的转换,就需要强行限制一个类或类型变量不能同时成为两个接口类型的子类”而这两个接口是同一个接口的不同参数化;
例如下面的代码就是非法的8>
Class Calendar implements Comparable
Class GregorianCalendar extends Calendar implements Comparable< GregorianCalendar>(Error)
GregorianCalendar会事先Comparable
这是同一接口的不同参数化;这一限制和类型擦柱的关系不是十分明确;下列的非泛型的版本就是合法的;
原因:有可能与合成的桥方法产生冲突。实现了Comparable
Public int comparaTo(Object other){
return compareTo(X) other
};
对于不同类型的;不能有两个这样的方法;
<9>泛型类型的继承规则:
例如:Employee和Manager。Pair
无论S和T有什么关系,通常Pair和Pair
继承泛型类
子类不是泛型类:需要给父类传递类型常量
当给父类传递的类型常量为String时,那么在父类中所有T都会被String替换!
子类是泛型类:可以给父类传递类型常量,也可以传递类型变量