在Java中将内部接口定义为类的实例变量
我对我正在看的一些源代码感到困惑,我正试图更好地理解它们。代码如下所示,但也可以在您自己玩的地方使用在Java中将内部接口定义为类的实例变量,java,interface,anonymous-inner-class,Java,Interface,Anonymous Inner Class,我对我正在看的一些源代码感到困惑,我正试图更好地理解它们。代码如下所示,但也可以在您自己玩的地方使用 import java.util.*; import java.lang.*; import java.io.*; class Ideone { public interface Fruit { public void apple(); } Fruit interfaceFruit; public void apple(){
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
public interface Fruit {
public void apple();
}
Fruit interfaceFruit;
public void apple(){
System.out.println("apple");
if (interfaceFruit != null) {
interfaceFruit.apple();
}
}
public void setFruit(Fruit f) {
interfaceFruit = f;
}
public static void main (String[] args) throws java.lang.Exception
{
Ideone test = new Ideone(){
@Override
public void apple() {
System.out.println("local override of apple");
}
};
System.out.println("1) ---");
test.apple();
Ideone test2 = new Ideone();
System.out.println("2) ---");
test2.apple();
test2.setFruit(new Fruit() {
@Override
public void apple() {
System.out.println("interface override of apple");
}
});
System.out.println("3) ---");
test2.apple();
}
}
输出为:
1) ---
local override of apple
2) ---
apple
3) ---
apple
interface override of apple
这段代码到底是怎么回事?在一个类内部声明了一个接口(所以,是内部接口,对吗?),然后该接口被声明为该类的实例变量。这就是我困惑的地方
我认为,如果为接口
水果
实例化了一个匿名内部类,我们将创建一个实现该接口的未命名类。我不完全理解的是接口如何或为什么存储在类的实例变量中。这样做的目的是什么?这种做法叫什么?这似乎很奇怪,我真的不确定有人会从中得到什么。这不是常见的代码,它只是一个练习,您可以看看它是如何工作的。因此,是的,事情可能看起来“奇怪”
我不完全了解接口如何或为什么存储在类的实例变量中
它不是存储的,而是定义的。可以在类中定义内部类和接口;举几个例子:
- 类和接口仅在类的内部逻辑中使用,其他地方不需要;通常这些被定义为私有的。与匿名类的工作原理大致相同
- 类和接口与类紧密耦合。例如,您为该bean定义了一个类和一个
实现;因为这样的比较器
只对该类的元素有用,所以可以将其定义为嵌套类。它就像另一个层次的“包装”比较器
Java.util.Map.Entry
类,它被Map
实现用来访问它们存储的键值对。声明:
Fruit interfaceFruit;
简单地说:“声明变量interfaceFruit
,该变量将用于保存对实现Fruit
的对象的引用
这样的变量可以包含对任何类的引用,只要它实现了接口。您可以使用它访问接口中定义的所有方法和常量,因为Java知道,无论该类是什么,它都将具有与Fruit
中的声明相匹配的重写方法(在本例中,它只有apple()
)
这类东西在Java中非常常用。它允许您使用变量来保存符合约定的任何对象,但可以使用它的不同实现。这种做法称为“编程到接口”。一个非常常见的示例是声明一个变量,如:
List<Integer> list;
无论指定给哪个类的对象(在Arrays.asList
的情况下,您甚至不知道将是哪个类),它都将拥有java.util.List
定义的所有操作,例如add()
或iterator()
因此,这同样适用于您的
Fruit
接口。它恰好是一个嵌套接口这一事实并不那么重要。相关:接口不存储在变量中。变量被声明为接口类型。重要的是要记住,接口的嵌套只是一个词汇,换句话说:嵌套接口总是隐式地静态的
。您所询问的行只是一个字段声明,完全独立于接口声明。您可以将接口移动到单独的源文件中,并且仍然可以将字段声明为水果
类型。关于“存储与定义”命令nt在您的回答中,我说的是这一行Fruit interfaceFruit;
接口被声明为一个实例变量否?然后稍后通过setFruit()进行设置
。正如你所说,这不是常见的代码,只是一个练习,你可以看看它是如何工作的。
-这让我感觉好一点。我写了这段代码,但它只是简化了代码库中的实际内容。接口声明为实例变量否?
否。接口完全由定义>接口Fruit{…}
,Fruit Fruit
所做的是声明一个变量,该变量可能引用实现Fruit
的类的实例(如果没有赋值,则为null)。接口被声明为内部接口,类中声明了一个类型为FROUT的实例变量。此外,无论是否显式,任何内部接口都被视为静态内部接口。@iullianr我不认为内部接口被视为静态内部接口。
。FROUT
interface被定义为Ideone.Fruit
,但不是静态接口。@MaxZoom被认为是一个静态接口,与静态内部类的意义相同。正如您在Ideone.Fruit中提到的,这意味着您不需要Ideone的实例来处理Fruit(同样,在代码中,您可以声明一个匿名类,该类实现了水果,而没有Ideone实例,就像静态内部类一样)。
List<Integer> list;
list = new LinkedList<Integer>();
list = new ArrayList<Integer>();
list = Arrays.asList(1,5,8,9);