在Java中将内部接口定义为类的实例变量

时间:2015-08-12 20:01:17

标签: java interface anonymous-inner-class

我对某些我正在查看的源代码感到困惑,并且我试图更好地理解。代码如下,但它也可用at Ideone,您可以自己使用它。

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

此代码究竟发生了什么?在类内部声明了一个接口(所以,一个内部接口,对吗?)然后将接口声明为该类的实例变量。这是我感到困惑的地方。

我认为发生的事情是,如果为接口Fruit实例化匿名内部类,我们将创建一个实现接口的未命名类。我没有完全理解的是接口是如何或为什么存储在类的实例变量中的。这样做的目的是什么?这种做法叫做什么?这看起来很奇怪,而且我不确定某人会从中得到什么。

2 个答案:

答案 0 :(得分:1)

这不是通常的代码,它只是一个练习,所以你可以看到它是如何工作的。所以是的,事情可能看起来很奇怪"。

(?i) # Case insensitive ^ # BOS (?= [a-z] ) # First char alpha (?! # Not these .*? (?: \._ # dot, underscore | _\. # underscore, dot | \.{2} # 2 or more dots | _{2} # 3 or more underscore | ( [a-z\d] ) # (1), 3 or more repeated alpha-num's \1{2} ) ) [a-z\d._]+ # Get valid char's: alpha-num, dot and underscore $ # EOS

它不是存储,它是定义的。您可以在类中定义内部类和接口;几个例子:

  • 类和接口仅用于类的内部逻辑,而其他地方则不需要;通常那些被定义为私人。与匿名类或多或少相同。

  • 类和接口与类紧密耦合。例如,您为该bean定义了一个类和What I'm not totally getting is how or why the interface is stored in an instance variable to the class实现;因为这样的Comparator仅对该类的元素有用,所以将其定义为嵌套类。它的工作方式与另一层次的包装"。

  • 相同

例如,我擅长控制传递给我的方法的值,所以,当它有意义时,我做的事情(非常愚蠢的例子)

Comparator

枚举仅用于访问类的逻辑,因此它在类中定义。

Java API中的示例是public class Calendar { public static enum WeekDay { MONDAY, ... SUNDAY; } public Date getNextDay(WeekDay weekDay) { ... } } 类,java.util.Map.Entry<K,V>实现使用它来访问它们存储的键值对。

答案 1 :(得分:1)

宣言:

Fruit interfaceFruit;

简单地说:&#34;声明变量interfaceFruit,它将用于保存对实现Fruit的对象的引用。

这样的变量可以保存对任何类的引用,前提是它实现了接口。你能用它来做的是访问界面中定义的所有方法和常量,因为Java知道无论类是什么,它都会有覆盖Fruit中声明的覆盖方法(在这种情况下) ,只有apple())。

这种东西在Java中非常常用。它允许您使用变量来保存符合合同的任何对象,但是在它的不同实现中使用它。这种做法被称为&#34;编程到界面&#34;。一个非常常见的例子是声明一个变量:

List<Integer> list;

(其中List是接口java.util.List),然后为其分配特定的实现:

list = new LinkedList<Integer>();
list = new ArrayList<Integer>();
list = Arrays.asList(1,5,8,9);

无论你指定的对象是哪一类(在Arrays.asList的情况下,你甚至都不知道会是哪一堂课),它将拥有全部java.util.List定义的操作 - 例如add()iterator()

因此同样适用于您的Fruit界面。它恰好是嵌套接口这一事实并不重要。