Java中的Interface是一种类型吗?

38

来自Java教程:

在Java中,一个类只能继承自一个类,但它可以实现多个接口。因此,对象可以有多个类型: 它们自己类的类型和所有实现的接口的类型。这意味着如果一个变量声明为一个接口类型,它的值可以引用任何实例化自实现该接口的类的对象

有人能为我提供一个基本伪类型吗?我不理解粗体字的那些句子。

答:该段讲述了Java语言中一个类只能继承自一个类,但是可以实现多个接口。因此,一个对象可以具有多种类型:它自己类的类型以及所有实现的接口的类型。这意味着,如果一个变量被声明为接口类型,则其值可以引用任何实现该接口的类实例化的对象。“对象可以有多个类型”这句话的意思就是Java中的多态性。
11个回答

66

让我们声明两个接口和一个实现了它们的类:

interface I1 { }

interface I2 { }

class C implements I1, I2 { }

对象可以拥有多个类型

在以下代码中,可以看到一个C实例的类型是CI1I2:

C c = new C();

boolean isC = (c instanceof C);   //true
boolean isI1 = (c instanceof I1); //true
boolean isI2 = (c instanceof I2); //true

现在让我们声明一个类B,该类同时实现了I1

class B implements I1 { }

如果一个变量被声明为接口类型,那么它的值可以引用任何从实现该接口的类实例化出来的对象。

如果我们声明一个类型为I1的变量,我们可以将其设置为C的实例,然后重新分配给B的实例:

I1 i1 = new C();
i1 = new B();

我们还可以将它重新分配给一个实例 D,其中D扩展了C

i1 = new D();

...

class D extends C { }

16

考虑以下示例:

Serializable s = new ArrayList();
在Java中,尽管Serializable是一个接口,但这是有效的代码,因为ArrayList实现了Serializable。因此,在这种情况下,我们将s视为类型为Serializable的变量。
现在假设我们用以下代码跟进上述代码:
s = "String object";

这也是有效的,因为String也实现了Serializable接口。由于我们将s声明为Serializable类型,它可以指向实现该接口的任何对象。


7

一个对象可以有多种类型

考虑以下代码片段:

public class MyClass extends ParentClass implements Interface1, Interface2 {    
    //some code    
}

这个类可以按照以下方式在不同的地方使用:

MyClass m1 = new MyClass();
ParentClass p = new MyClass();
Interface1 i1 = new MyClass();
Interface2 i2 = new MyClass();

当变量被声明为接口类型时,它的值可以引用任何从实现该接口的类中实例化出来的对象。
考虑上一段代码中的最后两行,Interface1类型的变量可以引用任何实现该接口的对象,因此如果我们有另一个实现Interface1接口的类,比如MyClass2,那么:
Interface1 i1 = new MyClass();
Interface1 i2 = new MyClasss2();
i1 = i2;
i1 = new MyClass2();

所有以前的任务都是有效的,因为MyClass和MyClass2实现了Interface1。

6
class Ball extends Rubber implements Jumping, Rolling, Squeezing {
   public void jump(){}
   public void roll(){}
   public void squeeze(){}
}

Ball b = new Ball();
Jumping j = new Ball();
j.jump();

//j.roll();         //CTE: Cannot resolve method roll()
((Ball) j).roll();  //but it still can be called if explicit cast to type Ball is used

3

String实现了多个接口,因此具有多个类型:

String s = "A String";
Comparable<String> comp = s;
CharSequece cs = s;
Serializable ser = s;

CharSequence 接口被多个类实现,因此一个 CharSequence 引用可以持有各种类型的对象:

CharSequence cs = "A String";
cs = new StringBuilder();
cs = new Segment();

3

对象可以有多种类型

例子:

public class Foo implements Runnable, Callable<Integer> {
  public void run() {}
  public Integer call() {return 1;}
}

Foo foo = new Foo();
Runnable r = foo;
Callable<Integer> c = foo;

示例:

如果一个变量被声明为接口类型,它的值可以引用任何从实现该接口的类实例化的对象。

Runnable r = new Foo();
r = Thread.currentThread();   //Thread implements Runnable

2
以下是正确的分配方式:
class AClass implements AInterface {
}


AInterface var = new AClass();

2
非常基础的例子-
List<String> list1=new ArrayList<String>();

由于 ArrayList 实现了 List 接口,因此我们可以使用 List 接口变量,即 list1,来引用由 ArrayList 创建的对象。


2
您引用的语句(来源在哪里?)是正确但具有误导性的——对象已经具有多种类型而不需要接口。
例如,"bimmelim" 的类型为 String,但它也具有 Object 类型。接口并不改变这一点,只是让 "bimmelim" 还具有 SerializableCharSequence 等类型。
实际上,我们可以争论是否应该说 "bimmelim" "具有" Object 类型,但肯定的是,对它的引用将适合于 Object 变量。
如果一个变量被声明为接口类型...例如:
CharSequence x ;

如果变量的值可以引用一个String对象,例如"bimmelim",或者它可能是一个StringBuffer,它是另一种实现CharSequence接口的类型。


1
考虑以下类和接口定义:
public class A { }

public class B extends A implements I { }

public interface I { }

以下语句都是合法的:
A first = new A();
B second = new B();
A third = new B();
I fourth = new B();

因为B实现了I并扩展了A,所以它可以在任何期望"I"或"A"的值的地方使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接