第四章 接口和

内部类

Interface &

Nested Class


第一节 接口(Interface)

1.Interface接口的定义和用法 (视频下载) (全部书籍)

先直接上大白话:马克-to-win:接口就是灰常灰常抽象的抽象类,我们可以就像用抽象类一样用接口,只不过,interface抽象到不能再抽象了,以至于里面不能有任何方法的实现, 只能都是空方法。紧接着来个例子:

例1.1---本章源码

interface OpenClose {
    void open();
    void close();
}
class Shop_mark_to_win implements OpenClose {
    public void open() {
        System.out.println("商店开门了---shop open");
    }
    public void close() {
        System.out.println("商店关门了---shop close");
    }
}
class Bottle_mark_to_win implements OpenClose {
    public void open() {
        System.out.println("打开瓶子,Open the Bottle");
    }
    public void close() {
        System.out.println("盖上瓶子Close the Bottle");
    }
}
public class Test {
    public static void main(String args[]) {
        OpenClose s = new Shop_mark_to_win();
        s.open();
        s.close();

        OpenClose b = new Bottle_mark_to_win();
        b.open();
        b.close();

        System.out.println("-----------------");
        OpenClose[] x = { s, b };
        for (int i = 0; i < x.length; i++) {
            x[i].open();
            x[i].close();
        }
    }
}


结果是:
商店开门了---shop open
商店关门了---shop close
打开瓶子,Open the Bottle
盖上瓶子Close the Bottle
-----------------
商店开门了---shop open
商店关门了---shop close
打开瓶子,Open the Bottle
盖上瓶子Close the Bottle


从上面例子看出,interface和抽象类的用法几乎一样,也有动态方法调度的概念。通过运用关键字interface,Java允许你定义一个接口。接口只有方法的定义,没有方法的任何实现。那这有什么意义呢?马克-to-win: 接口就像一个服务合同。接口只关心必须得干什么而不关心如何去实现它。有意义吗?有意义。马克-to-win:比如我们的软件经理总是关心工程师应该干什么?但软件经理从来不具体自己干什么事情,具体干什么事的工作留给工程师们去干。这种分工协作,带来了软件的巨大进步。国家部门只关心企业们应该做什么,但国家部门本身不做任何企业应该做的工作。分工协作带来了社会的巨大进步。

Interface is like a contracct
Interface focuses on behavior without being concerned about implementation details.
Interface totally isolate what must to do and how to do it.

2.Abstract类实现接口 (视频下载) (全部书籍)

马克-to-win:如果实现某接口的类是abstract类,则它可以不实现该接口所有的方法。但其非abstract的子类中必须拥有所有抽象方法的实在的方法体;(当然它abstract爹的也算作是它的)

If a class implements an interface, it must implement all of its methods in the interface, otherwise, this class must be an abstract class. if it is an abstract class, it can leave some methods in the interface unimplemented.refer to the following example.



例1.2---本章源码
interface OpenClose {
    void open();
    void close();
}
abstract class Door implements OpenClose {
    public void close() {
        System.out.println("旋转把手,拉!");
    }
}
/*AdvancedDoorMark_to_win这个类不需要实现close()。因为它已经有close()。它的close()位置在它的超类"Door"。
AdvancedDoorMark_to_win does not need to implement close(), because it already has
close(), the only thing is that the position of its close() is inside its
super class "Door"
*/
class AdvancedDoorMark_to_win extends Door {
    public void open() {
        System.out.println("旋转把手,推!");
    }

}
public class Test {
    public static void main(String args[]) {
        AdvancedDoorMark_to_win d = new AdvancedDoorMark_to_win();
        d.open();
        d.close();
    }
}
输出结果:
旋转把手,推!
旋转把手,拉!

3.接口持有多个类的共享常量 (视频下载) (全部书籍)

接口另一主要功能,马克-to-win: 可以使用接口来引入多个类的共享常量。所有的这些变量名都将作为常量看待。所有定义在接口中的常量都默认为public、static和final。原因见后面。

下面的例子当中,如果Server回答的结果是0或1,程序可读性太差,效果绝对没有YES或NO好。所以就把YES和NO放到了Client和Server的共同的接口ConstantbaseM_to_win当中。

note: the following example class Client and Server use the constants like NO and Yes at the same time, so, they define the constants in the interface of ConstantbaseM_to_win.



例1.3:

interface ConstantbaseM_to_win {
    static int NO = 0;
    int YES = 1;
}
class Server implements ConstantbaseM_to_win {
    int answer() {
        //通过其他渠道知道,今天不下雨
        return NO;
    }
}
class Client implements ConstantbaseM_to_win {
    static void ask(int result) {
        switch (result) {
        case NO:
            System.out.println("不下雨");
            break;
        case YES:
            System.out.println("下雨");
            break;
        }
    }
}
public class Test {
    public static void main(String args[]) {
        Client c = new Client();
        Server s = new Server();
        c.ask(s.answer());
    }
}


result is:
不下雨


4.实现多个接口Implementing Multiple Interface (视频下载) (全部书籍)

接口的优势:马克-to-win:类可以实现多个接口。与之相反,类只能继承一个超类(抽象类或其他类)。 A class can implement multiple interface, but a class can have only one superclass. this is also the difference between abstract class and interface.


例1.4:---本章源码

interface HandPhone {
    void talk();
}
interface Computer {
    void surfWeb();
}
class SmartPhoneMark_to_win implements HandPhone, Computer {
    public void surfWeb() {
        System.out.println("只要有wifi, 我就能上网");
    }
    public void talk() {
        System.out.println("马克-to-win: 和传统电话一样, 我能通话");
    }
}
public class Test {
    public static void main(String args[]) {
        SmartPhoneMark_to_win sp = new SmartPhoneMark_to_win();
        sp.surfWeb();
        sp.talk();
    }
}

输出结果:

只要有wifi, 我就能上网
马克-to-win: 和传统电话一样, 我能通话 

5.接口继承(Extending Interfaces)(视频下载) (全部书籍)

马克-to-win:对于以下的例子,Moto788这个产品只有照相takePhoto和通话talk的功能。而Moto888更为高级,除了照相和通话功能以外,还有mp3的功能。接口继承到底有什么意义呢?马克-to-win:1)通过接口继承很方便实现功能自由选择组合。同时发布Moto788和Moto888这两款产品 2)当初由于各方面的限制,设计有局限,比如Moto788没有mp3的功能,意识到这个缺陷后,通过接口继承升级到Moto888,很容易实现功能升级, 竞争。

例1.5:---本章源码

interface PhotoTake {

void takePhoto();
}
interface Mp3{
    void playMusic();
}
interface IMoto788 extends PhotoTake{
    void talk();
}
interface IMoto888 extends PhotoTake,Mp3{
    void talk();
}
class Moto788Mark_to_win implements IMoto788 {
    public void talk() {
        System.out.println("马克-to-win: 788和传统电话一样, 我能通话");
    }
    public void takePhoto() {
        System.out.println("马克-to-win: 我能照相");
    }
}
class Moto888Mark_to_win implements IMoto888 {
    public void talk() {
        System.out.println("马克-to-win: 888和传统电话一样, 我能通话");
    }
    public void takePhoto() {
        System.out.println("马克-to-win: 我能照相");
    }
    public void playMusic() {
        System.out.println("马克-to-win: 我能放音乐");
    }
}
public class Test {
    public static void main(String args[]) {
        Moto888Mark_to_win m888 = new Moto888Mark_to_win();
        m888.talk();
        Moto788Mark_to_win m788 = new Moto788Mark_to_win();
        m788.talk();
    }
}


输出结果:

马克-to-win: 888和传统电话一样, 我能通话
马克-to-win: 788和传统电话一样, 我能通话

6.总结性深一层次综合剖析接口概念【新手可忽略不影响继续学习】 (视频下载) (全部书籍)

通过以上的学习, 我们知道,所有定义在接口中的常量都默认为public、static和final。所有定义在接口中的方法默认为public和abstract。马克-to-win:当时Sun公司为什么要把java的接口设计发明成这样?
1)为什么接口中的属性都默认为static和final?Sun公司当初为什么要把java的接口设计发明成这样?
【新手可忽略不影响继续学习】(视频下载) (全部书籍)
答:马克-to-win:接口中如果可能定义非final的变量的话,而方法又都是abstract的,变量的修改就需要实现类来完成。马克-to-win,这样一来就有悖于Sun公司开始设计interface的初衷。interface就像一个合同,规定后来的类A和B, 都按照这个合同来做事,怎么能谁想怎么改就怎么改?另外,为什么必须为static呢?马克-to-win,这样,未来的子类的static方法也能访问到它,可以最大限度的发挥接口属性的功能。

2)接口和抽象类有什么区别?(视频下载) (全部书籍)
答:马克-to-win:抽象类里可以有实现的方法,接口里不能有,所以相对来讲各方面实现都简单(尤其动态方法调度)另外:类可以实现多个接口。反过来说,也正是抽象类一个致命伤:类只能继承一个超类(抽象类或其他类)。
3)为什么接口能胜任作为和外部系统打交道的合同而抽象类就不行?(见下面我的山和车,肥皂的例子)【新手可忽略不影响继续学习】
答:马克-to-win:假设你用抽象类作为合同,(视频下载) (全部书籍)外部系统有个类A,它本来固有就必须得继承一个类B,现在还必须得继承你这个抽象类,语法上不允许。反过来,如果你不用抽象类而用接口作为合同,语法上就允许了。马克-to-win:这样,接口的多实现性,就等同于另外一句话:“不占继承资源”。外部系统具有很强的不可预见性,换句话说, 谁知道你过去的类继承没继承其他的类,我不管,反正我的合同内容写在一个接口中,即使你过去必须继承一个别的类,也不影响你再多实现一个我,因为我是接口。
4)为什么接口中的属性和方法都默认为public?Sun公司当初为什么要把java的接口设计发明成这样? 【新手可忽略不影响继续学习】(视频下载) (全部书籍)
答:如上所述,马克-to-win:既然接口强于抽象类能胜任作为和外部系统打交道的合同。换句话说,一般来讲和外部系统打交道,自然考虑用“接口”。“外部”二字自然让我们做出如下结论:属性和方法都应默认为public。因为是和外部系统打交道,存在很大的未知性,马克-to-win:我并不知道未来外部别人怎么用我们的接口,所以尽量少给别人设置障碍(少添点堵),就设置权限为public,出于这种考虑,Sun公司一开始就规定,接口属性和方法默认就为public。




5)Sun公司把接口设计成合同的作用,有什么意义, 举个实例?
【新手可忽略不影响继续学习】
答:马克-to-win,比如我有一个系统,如果我想完成我的功能,我要求给我的参数只有满足一定的条件才可以让我系统正常工作。这个条件我当然必须得在合同中规定出来!(当然这里合同就是接口),参见以下的例子:马克-to-win, QuerySystem(查询系统)是个外部系统。它可以接受任何类型的对象,只要你实现Priceable这个接口,乐意遵守Priceable订的合同,Car和Soap乐意遵守,于是就能进入系统让QuerySystem正常工作,马克-to-win:而Mountain不遵守合同(拒不实现Priceable订立的接口),于是即使想进入系统,也会报语法错误。肥皂和车都可定价(priceable),山不能被定价。

例1.6.2:---本章源码

interface Priceable{
    double getPrice();
}
class SoapMark_to_win implements Priceable {
    double price;
    SoapMark_to_win(double price) {
        this.price = price;
    }
    public double getPrice()
    {
        return price;
    }
}
class Car implements Priceable {
    public double getPrice()
    {
        return 0;
    }
}
class Mountain {//这里mountain未实现接口
    double height;
    Mountain(double height)
    {
        this.height=height;
    }
}
class QuerySystem{
     Priceable pIn;
/* 下句话表示, QuerySystem,只接受实现了Priceable类型的对象,马克-to-win:只接受按Priceable这个合同办事的人,能接受Car, SoapMark_to_win,不能接受Mountain, 因为他没有实现Priceable接口*/     
     void accept(Priceable p)
     {
         pIn=p;
     }
     void printInfo()
     {
         System.out.println(pIn.getPrice());
     }
}
public class Test {
    public static void main(String[] args) {
        QuerySystem qs=new QuerySystem();
        Car car=new Car();       
        SoapMark_to_win soap=new SoapMark_to_win(8);
        Mountain mountain=new Mountain(2000);//马克-to-win:
        qs.accept(soap);
        qs.printInfo();
        qs.accept(car);
        qs.printInfo();
//        qs.accept(mountain);//错误,未遵守合同,未实现接口,直接报错
    }
}

输出结果:

8.0
0.0





第二节 内部类Nested class


什么是内部类?马克-to-win:一句话:类中还有类。(视频下载) (全部书籍)里边的叫内部类, 外边的叫外层类。有什么用?1)像文件夹一样,文件放文件夹里更清晰,内部类放外层类中, 清晰。主要从编程序的逻辑角度出发,有用。比如书类内部的插页类。2)通过使用private,内部类不为外面所知, 安全。马克-to-win:用法上: 内部类(inner)可以访问外层类的成员,包括private成员。但是,外面不能直接访问内部类的成员。 分类:主要有i)实例内部类和 ii)静态内部类。还是从外部类实例有哪些属性存在来单步调试看,理解依然比较简单。

1.Instance inner class定义,用途和用法 (视频下载) (全部书籍)

重要语法:马克-to-win:1)实例内部类一定得有个外层类的实例和它绑定在一起,所以可以用This指针。所以必须先实例化外层类之后才能再实例化内部类。(生活中的例子就是子宫和胚胎(不算试管婴儿!))2)语法规定:实例内部类不能有静态的属性或方法,为什么?因为没有外层类的实例就不应该有实例内部类的任何东西存在,包括内部类的静态属性,但静态属性应该在main方法执行时创建,这样就会产生矛盾,所以规定实例内部类不能有静态的属性或方法。马克-to-win:2)既然每个内部类实例都可以改变他们共同的外层类的静态属性或实例属性,他们成为内部类实例们可以交互的地方。(下例中的shell_x,在不断增长。)

例2.1a:类中有个内部类属性。

class ShellMark_to_win {
    int shell_x = 100;//既然每个内部类实例都可以改变这里的外层类静态属性或实例属性,马克-to-win:这里成为内部类实例们可以交互的地方
    static int n;
    Core core;
    void visitCore() {
        core = new Core();
        core.y=8;
        core.display();
    }
    // 下面是个实例内部类,必须有个外层类实例,才能有这个内部类实例。所以就有了this这个概念。
    class Core {
/* 下一句错误,根据语法:马克-to-win:静态的域或方法只能出现在静态类或最外层类上。The field m cannot be declared static; static fields can only be declared in static inner class or top level classes,*/     
  //    static int m=9;
        int y = 10; // y is local to core
        void display() {
            shell_x=shell_x+20;
            n=n+1;//轻松访问外层类的静态变量
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
    }
    Core newC()
    {
        return new Core();
    }
    void showy() {
        // y=9; // 错误,马克-to-win:外层类不能直接访问内部类的属性。error,y not known here! System.out.println(y);
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
        shell.visitCore();
        ShellMark_to_win.Core sc=shell.new Core();//内部类实例是存在于外部对象里的。
        sc.display();
        ShellMark_to_win.Core sc1=shell.newC();
        sc1.display();
/* 不能像下面这样写, 因为Core 是内部类。   can not resolve Core class ,because Core class are defiened as ShellMark_to_win's inner class. */
        //Core core = new Core();
    }
}

结果:
n is 1 display: shell_x and y 120 120 8 8
n is 2 display: shell_x and y 140 140 10 10
n is 3 display: shell_x and y 160 160 10 10


例2.1:---本章源码
class ShellMark_to_win {
    int shell_x = 100;//既然每个内部类实例都可以改变这里的外层类静态属性或实例属性,马克-to-win:这里成为内部类实例们可以交互的地方
    static int n;
    void visitCore() {
       Core core = new Core();
        core.y=8;
        core.display();
    }
    // 下面是个实例内部类,必须有个外层类实例,才能有这个内部类实例。所以就有了this这个概念。
    class Core {
/* 下一句错误,根据语法:马克-to-win:静态的域或方法只能出现在静态类或最外层类上。The field m cannot be declared static; static fields can only be declared in static inner class or top level classes,*/      
  //    static int m=9;
        int y = 10; // y is local to core
        void display() {
            shell_x=shell_x+20;
            n=n+1;//轻松访问外层类的静态变量
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
    }
    Core newC()
    {
        return new Core();
    }
    void showy() {
        // y=9; // 错误,马克-to-win:外层类不能直接访问内部类的属性。error,y not known here! System.out.println(y);
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
        shell.visitCore();
        ShellMark_to_win.Core sc=shell.new Core();//内部类是存在于外部对象里的。
        sc.display();
        ShellMark_to_win.Core sc1=shell.newC();
        sc1.display();
/* 不能像下面这样写, 因为Core 是内部类。   can not resolve Core class ,because Core class are defiened as ShellMark_to_win's inner class. */
        //Core core = new Core();
    }
}


结果如下:
n is 1 display: shell_x and y 120 120 8 8
n is 2 display: shell_x and y 140 140 10 10
n is 3 display: shell_x and y 160 160 10 10
       
2.当内部类中还有一个内部类,下面给出了一个实例。【新手可忽略不影响继续学习】(以下多出代码, 用蓝色标记)(视频下载) (全部书籍)

例2.2:---本章源码
class ShellMark_to_win {
    int shell_x = 100;//马克-to-win:既然每个内部类实例都可以改变这里的外层类静态属性或实例属性,这里成为内部类实例们可以交互的地方
    static int n;
    void visitCore() {
        Core core = new Core();
        core.y=8;
        core.display();
    }
    // 下面是个实例内部类,必须有个外层类实例,才能有这个内部类实例。所以就有了this这个概念。
    class Core {
/* 下一句错误,根据语法:马克-to-win:静态的域或方法只能出现在静态类或最外层类上。The field m cannot be declared static; static fields can only be declared in static inner class or top level classes,*/       
  //    static int m=9;
        int y = 10; // y is local to core
        void display() {
            shell_x=shell_x+20;
            n=n+1;//轻松访问外层类的静态变量
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
        class CoreCore{
            void displayDis() {
                Core.this.display();
            }
        }

    }
    Core newC()
    {
        return new Core();
    }
    void showy() {
        // y=9; // 错误,马克-to-win:外层类不能直接访问内部类的属性。error,y not known here! System.out.println(y);
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
        shell.visitCore();
        ShellMark_to_win.Core sc=shell.new Core();//马克-to-win:内部类是存在于外部对象里的。
        sc.display();
        ShellMark_to_win.Core.CoreCore scc=sc.new CoreCore();
        scc.displayDis();

        ShellMark_to_win.Core sc1=shell.newC();
        sc1.display();
/* 不能像下面这样写, 因为Core 是内部类。   can not resolve Core class ,because Core class are defiened as ShellMark_to_win's inner class. */
        //Core core = new Core();
    }
}

result is:
n is 1 display: shell_x and y 120 120 8 8
n is 2 display: shell_x and y 140 140 10 10
n is 3 display: shell_x and y 160 160 10 10
n is 4 display: shell_x and y 180 180 10 10


      
3.接口interface和private内部类协同工作【新手可忽略不影响继续学习】(视频下载) (全部书籍)
马克-to-win:由于是private内部类,外面无法访问甚至无法看到你编的源代码(如果在不同的包中),非常安全。外界只能调用接口中的方法。下例中访问不了Core,甚至你不知道有Core的存在。给你的就是外部的接口,供你使用。马克-to-win:我们一直没讲class 如何能private, 这里内部类时,就可以用private了。且内部类随便访问外部类的东西, 这就非常有力度了, 可以用到外部类所有的资源!

例2.3---本章源码

interface CoreI
{   
    void display();
}
class ShellMark_to_win {
    int shell_x = 100;
    static int n;
    // 下面内部类是private,只能外层类的方法才能访问到, 非常安全
    private class Core implements CoreI {
/* 下一句错误,马克-to-win:根据语法:静态的域或方法只能出现在静态类或最外层类上。The field m cannot be declared static; static fields can only be declared in static inner class or top level classes,*/      
  //    static int m=9;
        int y = 10; // y is local to core
        public void display() {
            shell_x=shell_x+20;
            n=n+1;//马克-to-win:轻松访问外层类的静态变量
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
    }
    Core newC()
    {
        return new Core();
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
     //   ShellMark_to_win.Core sc=shell.new Core();//错误,马克-to-win: 因为Core是私有的
        CoreI sc1=shell.newC();
        sc1.display();
    }
}

结果是:

n is 1 display: shell_x and y 120 120 10 10


4静态内部类(Static Inner Classes)(视频下载) (全部书籍)

马克-to-win:这里的内部类的static,意思是它可以不用实例化外部类,就自己单独被实例化,单独存在(有点像生活中的办公室和办公桌(独立于办公室,办公桌也可以存在)),静态方法不就不用实例化类,直接用吗?就实例化而言,静态内部类和外层类之间完全没有任何关系,相互独立。谁爱怎么样,就怎么样!谁想实例化谁就实例化, 不管对方的感受。当然要想让它们有关系,也可以,见下面例子中的tc.core=nc;

重要语法:马克-to-win:1)静态内部类里的任何方法(静态或非静态)不允许访问外层类里的实例属性或方法。(因为外层类本身可能没有被实例化),想访问通过下面例子中的tc.core=nc。2)静态属性和方法无论在外层类还是静态内部类, 都可以被任意调用(对方或自己或测试类)。

例2.4

class ShellMark_to_win {
    static  int ss_i ;
    private int si_k;
    Core core;
    static class Core {
        static  int cs_m ;
        int ci_j;
        public Core(int j) {
            ss_i = 2;//可以直接访问外层类的静态域
            cs_m=3;
            //k=9;//马克-to-win:compile error,static class can not refer to a non-static field,因为静态内部类可以脱离外层实例而单独存在,静态内部类可能已经被实例化,而外层类没有被实例化,外层的实例变量就不能被访问。像原来的静态 方法似的,不能访问实例变量
            this.ci_j = j;
        }
        public String toString()
        {
            //ShellMark_to_win.changTopValue();//可以访问外层类的静态方法
            //insMethod();//不能从静态类里访问外层类的实例方法。
            return "ci_j=" + ci_j + ";ss_i=" + ss_i+" ;cs_m="+cs_m;// 马克-to-win:这里不能写+k,因为cocs_mpile error,static class can not refer to a non-static field,像原来的静态方法似的,不能访问实例变量
        }
        static int changValue()
        {   //inscs_method();//不能从静态类里访问实例方法。
            cs_m=cs_m+2;
            ss_i=ss_i+2;
            //k=9;//马克-to-win:这里不能写+k,因为compile error,static class can not refer to a non-static field,像原来的静态方法似的,不能访问实例变量
          //  ShellMark_to_win.changTopValue();完全可以调用
            System.out.println("cs_m is "+cs_m+" ss_i is"+ss_i);
            //ci_j=ci_j+2;//错误, 静态方法无法访问非静态变量
            return cs_m;
        }
    }
    public String toString() {
        //Core.changValue();//可以访问静态内部类的静态方法    
        return "si_k=" + si_k + ";ss_i=" + ss_i+"cs_m is "+Core.cs_m;
    }
    void insMethod()
    {
    
    }
    static int changTopValue()
    {
        ShellMark_to_win.Core.cs_m=ShellMark_to_win.Core.cs_m+2;
        ss_i=ss_i+2;
        return ss_i;
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(ShellMark_to_win.ss_i+" "+ShellMark_to_win.Core.cs_m);
        System.out.println(ShellMark_to_win.changTopValue());
        System.out.println(ShellMark_to_win.Core.changValue());
        ShellMark_to_win tc = new ShellMark_to_win();
        System.out.println("tc is "+tc);
/* 马克-to-win:since Core is static member, we can use in this way.不用实例化外部类, 就可以单独存在 */
        ShellMark_to_win.Core nc = new ShellMark_to_win.Core(5);
/*加上下面两句话,可以让外层类和内部类产生联系而且相互改值*/      
   //     tc.core=nc;
   //     tc.core.ci_j=100;
        System.out.println("nc is "+nc);
        nc.changValue();
        System.out.println("tc is "+tc);
    }
}


rsult is:
0 0
2
cs_m is 4 ss_i is4
4
tc is si_k=0;ss_i=4cs_m is 4
nc is ci_j=5;ss_i=2 ;cs_m=3
cs_m is 5 ss_i is4
tc is si_k=0;ss_i=4cs_m is 5


5.局部内部类Local inner class  (视频下载) (全部书籍)

马克-to-win:什么叫局部内部类?内部类声明位置:1.它的外部类的范围之内。2.在几个程序块的范围之内。例如,由方法定义的块中或甚至在for循环体内部。局部内部类有什么意义?意义就是:你希望这个类只被解决某个问题用,任何其他人,其他地方都不能用它。就像临时变量一样。马克-to-win:生活中百年不遇我们去海边玩,专门裁出一块布来铺在沙滩上, 但这块布干什么别的事都不合适,就属于这种情况。 

例2.5---本章源码

class ShellMark_to_win {
    int x = 100;
    void test() {
        for (int i = 0; i < 2; i++) {
/*马克-to-win:for循环之外,Core类不存在。 outside of this for loop, inner can not be used. */
            class Core {
                void display() {
                    System.out.println("外部类的x=" + x);
                }
            }
            Core inner = new Core();
            inner.display();
        }
    //    Core inner = new Core(); //错误找不到Core。
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win s = new ShellMark_to_win();
        s.test();
    }
}


result is:
外部类的x=100
外部类的x=100

6.局部内部类访问外边的局部变量时,此变量必须为final类型 (视频下载) (全部书籍)

马克-to-win:由于技术方面的限制,java的设计者们做出如下语法规定:局部内部类访问外边的局部变量时,此变量必须为final类型,(为什么请参考我的参考目录)马克-to-win:否则会报一个错误:Cannot refer to a non-final variable i inside an inner class defined in a different method

例2.6---本章源码

class ShellMark_to_win {

   int x = 100;//x是类变量, 内部类访问时不用加final。
    void test() {
        for (int i = 0; i < 2; i++) {
/*马克-to-win:下面的y和str是局部变量,内部类访问时必须加final  */
            final int y=6;  
            final String str="aaa";
            class Core {
                void display() {
                    System.out.println("外部类的x=" + x+y+str);
                }
            }
            Core inner = new Core();
            inner.display();
        }
    //    Core inner = new Core(); //错误找不到Core。
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win s = new ShellMark_to_win();
        s.test();
    }
}

输出结果:

外部类的x=1006aaa
外部类的x=1006aaa  

7 Anonymous inner class (视频下载) (全部书籍)

马克-to-win:有时如此简单,都没有必要清清楚楚明确出类名,用一下就完,就用匿名内部类。注意: 下面的new FigureMark_to_win(){。。。。};的语法形式。它和以往的new FigureMark_to_win()不同,现在的这个new的是FigureMark_to_win的子类(否则“我啥也不是”, 应该被打印出来。)。

例2.7_0:

class FigureMark_to_win {
    void whoAmI(){
       System.out.println("我啥也不是");   
    }
}
class Triangle extends FigureMark_to_win {
    void whoAmI() {
        System.out.println("三角形!");
    }
}
public class Test {
    public static void main(String[] args) {
        Triangle d = new Triangle();
        d.whoAmI();
        new Triangle().whoAmI();//连指针都省了
/* 马克-to-win:下面这句程序,都没有像上面一样提出一个Triangle类的概念,主要是如此简单,都没有必要清清楚楚明确出类名,所以就直接 new FigureMark_to_win(){。。。。}; ,马克-to-win: 大家注意一下格式和分号。 even though the next statemnt new a abstract class which is not
allowed, it implement the method of whoAmI, so it is not the real abstract class instantiation.
*/
        FigureMark_to_win a = new FigureMark_to_win() {
            void whoAmI() {
                System.out.println("长方形!");
            }
        };
        a.whoAmI();
        new FigureMark_to_win() {
            void whoAmI() {
                System.out.println("圆形");
            }
        }.whoAmI();//连指针都省了
    }
}
结果:

三角形!
三角形!
长方形!
圆形

匿名内部类的父类也可以是抽象类或接口。以下给出例子:

例2.7---本章源码

abstract class FigureMark_to_win {
    abstract void whoAmI();
}
class Triangle extends FigureMark_to_win {
    void whoAmI() {
        System.out.println("三角形!");
    }
}
public class Test {
    public static void main(String[] args) {
        Triangle d = new Triangle();
        d.whoAmI();
        new Triangle().whoAmI();//连指针都省了
/* 马克-to-win:下面这句程序,都没有像上面一样提出一个Triangle类的概念,主要是如此简单,都没有必要清清楚楚明确出类名,所以就直接 new FigureMark_to_win(){。。。。},马克-to-win: 大家注意一下格式和分号。 even though the next statemnt new a abstract class which is not
allowed, it implement the method of whoAmI, so it is not the real abstract class instantiation.
*/
        FigureMark_to_win a = new FigureMark_to_win() {
            void whoAmI() {
                System.out.println("长方形!");
            }
        };
        a.whoAmI();
        new FigureMark_to_win() {
            void whoAmI() {
                System.out.println("圆形");
            }
        }.whoAmI();//连指针都省了
    }
}



result is:
三角形!
三角形!
长方形!
圆形

下面的例子说明匿名内部类的匿名构造函数的用法 (视频下载) (全部书籍)

例2.7.2_0

interface FigureMark_to_win {
    void whoAmI();
}
public class Test {
    public static void main(String[] args) {
        FigureMark_to_win ttm = new FigureMark_to_win() {
            private String msg = "三角形";
           
            {//马克-to-win: 匿名构造函数
                msg = "长方形";
            }
            public void whoAmI() {
                System.out.println(msg);
            }
        };
        ttm.whoAmI();
    }
}


result is:
长方形

结合前面的讨论,内部类访问外边的局部变量时,此变量必须为final类型,我们给出下面例子:

例2.7.2_1:

interface FigureMark_to_win {
    void whoAmI();
}
public class Test {
    public static void main(String[] args) {
        final String out="长方形";
        FigureMark_to_win ttm = new FigureMark_to_win() {
            private String msg = "三角形";
           
            {//马克-to-win: 匿名构造函数
                msg = out;
            }
            public void whoAmI() {
                System.out.println(msg);
            }
        };
        ttm.whoAmI();
    }
}

结果:

长方形

例2.7.2_2:(参考我的第一章:命令行参数)

注意我运行时, 命令行参数给进的是“长方形在命令行”

interface FigureMark_to_win {
    void whoAmI();
}
public class Test {
    public static void main(final String[] args) {
        FigureMark_to_win ttm = new FigureMark_to_win() {
            private String msg = "三角形";
            
            {//马克-to-win: 匿名构造函数
                msg = args[0];
            }
            public void whoAmI() {
                System.out.println(msg);
            }
        };
        ttm.whoAmI();
    }
}
结果:
长方形在命令行

例2.7.2---本章源码

interface FigureMark_to_win {
    void whoAmI();
}
public class Test {
    public static void main(final String[] args) {
        FigureMark_to_win ttm = new FigureMark_to_win() {
            private String msg = "三角形";
           
            {//马克-to-win: 匿名构造函数
                msg = "长方形";
            }
            public void whoAmI() {
                System.out.println(msg);
            }
        };
        ttm.whoAmI();
    }
}


result is:
长方形

附录:本章源码 (视频下载) (全部书籍)

例1.1

interface OpenClose {
    void open();
    void close();
}
class Shop_mark_to_win implements OpenClose {
    public void open() {
        System.out.println("商店开门了---shop open");
    }
    public void close() {
        System.out.println("商店关门了---shop close");
    }
}
class Bottle_mark_to_win implements OpenClose {
    public void open() {
        System.out.println("打开瓶子,Open the Bottle");
    }
    public void close() {
        System.out.println("盖上瓶子Close the Bottle");
    }
}
public class Test {
    public static void main(String args[]) {
        OpenClose s = new Shop_mark_to_win();
        s.open();
        s.close();

        OpenClose b = new Bottle_mark_to_win();
        b.open();
        b.close();

        System.out.println("-----------------");
        OpenClose[] x = { s, b };
        for (int i = 0; i < x.length; i++) {
            x[i].open();
            x[i].close();
        }
    }
}


结果是:
商店开门了---shop open
商店关门了---shop close
打开瓶子,Open the Bottle
盖上瓶子Close the Bottle
-----------------
商店开门了---shop open
商店关门了---shop close
打开瓶子,Open the Bottle
盖上瓶子Close the Bottle


例1.2:

interface OpenClose {
    void open();
    void close();
}
abstract class Door implements OpenClose {
    public void close() {
        System.out.println("旋转把手,拉!");
    }
}

class AdvancedDoorMark_to_win extends Door {
    public void open() {
        System.out.println("旋转把手,推!");
    }

}
public class Test {
    public static void main(String args[]) {
        AdvancedDoorMark_to_win d = new AdvancedDoorMark_to_win();
        d.open();
        d.close();
    }
}
输出结果:
旋转把手,推!
旋转把手,拉!


例1.3:

interface ConstantbaseM_to_win {
    static int NO = 0;
    int YES = 1;
}
class Server implements ConstantbaseM_to_win {
    int answer() {
       
        return NO;
    }
}
class Client implements ConstantbaseM_to_win {
    static void ask(int result) {
        switch (result) {
        case NO:
            System.out.println("不下雨");
            break;
        case YES:
            System.out.println("下雨");
            break;
        }
    }
}
public class Test {
    public static void main(String args[]) {
        Client c = new Client();
        Server s = new Server();
        c.ask(s.answer());
    }
}


result is:
不下雨


例1.4:
interface HandPhone {
    void talk();
}
interface Computer {
    void surfWeb();
}
class SmartPhoneMark_to_win implements HandPhone, Computer {
    public void surfWeb() {
        System.out.println("只要有wifi, 我就能上网");
    }
    public void talk() {
        System.out.println("马克-to-win: 和传统电话一样, 我能通话");
    }
}
public class Test {
    public static void main(String args[]) {
        SmartPhoneMark_to_win sp = new SmartPhoneMark_to_win();
        sp.surfWeb();
        sp.talk();
    }
}

输出结果:

只要有wifi, 我就能上网
马克-to-win: 和传统电话一样, 我能通话

例1.5:

interface PhotoTake {
    void takePhoto();
}
interface Mp3{
    void playMusic();
}
interface IMoto788 extends PhotoTake{
    void talk();
}
interface IMoto888 extends PhotoTake,Mp3{
    void talk();
}
class Moto788Mark_to_win implements IMoto788 {
    public void talk() {
        System.out.println("马克-to-win: 788和传统电话一样, 我能通话");
    }
    public void takePhoto() {
        System.out.println("马克-to-win: 我能照相");
    }
}
class Moto888Mark_to_win implements IMoto888 {
    public void talk() {
        System.out.println("马克-to-win: 888和传统电话一样, 我能通话");
    }
    public void takePhoto() {
        System.out.println("马克-to-win: 我能照相");
    }
    public void playMusic() {
        System.out.println("马克-to-win: 我能放音乐");
    }
}
public class Test {
    public static void main(String args[]) {
        Moto888Mark_to_win m888 = new Moto888Mark_to_win();
        m888.talk();
        Moto788Mark_to_win m788 = new Moto788Mark_to_win();
        m788.talk();
    }
}


输出结果:

马克-to-win: 888和传统电话一样, 我能通话
马克-to-win: 788和传统电话一样, 我能通话


例1.6.1:
以下例子,假如A实现IA接口,IA接口里面有printIProtected,这个方法是protected。

package p1;
public class A {
    protected int i;
    protected void printIProtected() {
        System.out.println("i=" + i);
    }
}

package p2;
import p1.A;
public class Test extends A {
    public static void main(String[] args) {
        A a=new A();
        
    }

}


例1.6.2:

interface Priceable{
    double getPrice();
}
class SoapMark_to_win implements Priceable {
    double price;
    SoapMark_to_win(double price) {
        this.price = price;
    }
    public double getPrice()
    {
        return price;
    }
}
class Car implements Priceable {
    public double getPrice()
    {
        return 0;
    }
}
class Mountain {
    double height;
    Mountain(double height)
    {
        this.height=height;
    }
}
class QuerySystem{
     Priceable pIn;

     void accept(Priceable p)
     {
         pIn=p;
     }
     void printInfo()
     {
         System.out.println(pIn.getPrice());
     }
}
public class Test {
    public static void main(String[] args) {
        QuerySystem qs=new QuerySystem();
        Car car=new Car();       
        SoapMark_to_win soap=new SoapMark_to_win(8);
        Mountain mountain=new Mountain(2000);//马克-to-win:
        qs.accept(soap);
        qs.printInfo();
        qs.accept(car);
        qs.printInfo();

    }
}

输出结果:

8.0
0.0


例2.1:
class ShellMark_to_win {
    int shell_x = 100;
    static int n;
    void visitCore() {
        Core core = new Core();
        core.y=8;
        core.display();
    }
   
    class Core {
   
 
        int y = 10;
        void display() {
            shell_x=shell_x+20;
            n=n+1;
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
    }
    Core newC()
    {
        return new Core();
    }
    void showy() {
       
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
        shell.visitCore();
        ShellMark_to_win.Core sc=shell.new Core();
        sc.display();
        ShellMark_to_win.Core sc1=shell.newC();
        sc1.display();

      
    }
}


结果如下:
n is 1 display: shell_x and y 120 120 8 8
n is 2 display: shell_x and y 140 140 10 10
n is 3 display: shell_x and y 160 160 10 10


例2.2:
class ShellMark_to_win {
    int shell_x = 100;//马克-to-win:
    static int n;
    void visitCore() {
        Core core = new Core();
        core.y=8;
        core.display();
    }
   
    class Core {
   
 
        int y = 10;
        void display() {
            shell_x=shell_x+20;
            n=n+1;
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
        class CoreCore{
            void displayDis() {
                Core.this.display();
            }
        }

    }
    Core newC()
    {
        return new Core();
    }
    void showy() {
       
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
        shell.visitCore();
        ShellMark_to_win.Core sc=shell.new Core();//马克-to-win:
        sc.display();
        ShellMark_to_win.Core.CoreCore scc=sc.new CoreCore();
        scc.displayDis();

        ShellMark_to_win.Core sc1=shell.newC();
        sc1.display();
       
    }
}

result is:
n is 1 display: shell_x and y 120 120 8 8
n is 2 display: shell_x and y 140 140 10 10
n is 3 display: shell_x and y 160 160 10 10
n is 4 display: shell_x and y 180 180 10 10


例2.3

interface CoreI
{   
    void display();
}
class ShellMark_to_win {
    int shell_x = 100;
    static int n;
   
    private class Core implements CoreI {
  
 
        int y = 10;
        public void display() {
            shell_x=shell_x+20;
            n=n+1;//马克-to-win:
            System.out.println("n is "+n+" display: shell_x and y " + shell_x + " "+ShellMark_to_win.this.shell_x+ " " + y+ " "+this.y);
        }
    }
    Core newC()
    {
        return new Core();
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win shell = new ShellMark_to_win();
    
        CoreI sc1=shell.newC();
        sc1.display();
    }
}

结果是:

n is 1 display: shell_x and y 120 120 10 10


例2.4

class ShellMark_to_win {
    static  int i ;
    private int k;
    static class Core {
        static  int m ;
        int j;
        public Core(int j) {
            i = 2;
            m=3;
           
            this.j = j;
        }
        public String toString()
        {
          
           
            return "j=" + j + ";i=" + i+" ;m="+m;
        }
        static int changValue()
        {  
            m=m+2;
            i=i+2;
          
         
            System.out.println("m is "+m+" i is"+i);
          
            return m;
        }
    }
    public String toString() {
       
        return "k=" + k + ";i=" + i+"m is "+Core.m;
    }
    void insMethod()
    {
      
    }
    static int changTopValue()
    {
        ShellMark_to_win.Core.m=ShellMark_to_win.Core.m+2;
        i=i+2;
        return i;
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(ShellMark_to_win.i+" "+ShellMark_to_win.Core.m);
        System.out.println(ShellMark_to_win.changTopValue());
        System.out.println(ShellMark_to_win.Core.changValue());
        ShellMark_to_win tc = new ShellMark_to_win();
        System.out.println("tc is "+tc);
        ShellMark_to_win.Core nc = new ShellMark_to_win.Core(5);
        System.out.println("nc is "+nc);
        nc.changValue();
        System.out.println("tc is "+tc);
    }
}

rsult is:
0 0
2
m is 4 i is4
4
tc is k=0;i=4m is 4
nc is j=5;i=2 ;m=3
m is 5 i is4
tc is k=0;i=4m is 5


例2.5

class ShellMark_to_win {
    int x = 100;
    void test() {
        for (int i = 0; i < 2; i++) {

            class Core {
                void display() {
                    System.out.println("外部类的x=" + x);
                }
            }
            Core inner = new Core();
            inner.display();
        }
   
    }
}
public class Test {
    public static void main(String args[]) {
        ShellMark_to_win s = new ShellMark_to_win();
        s.test();
    }
}


result is:
外部类的x=100
外部类的x=100