1. 内部类的特性

  • 他允许你把一些逻辑相关的类组织在一起。

2. 使用.this

  • 如果你需要在内部类中堆外部类进行应用,可以使用外部类的名字后面加.this。下面展示了如何使用 .this

    package net.mindview.innerclasses;
    
    public class DotThis {
    void f(){
    System.out.println("DotThis.f()");
    } public class Inner {
    public DotThis outer() {
    System.out.println(DotThis.this);
    return DotThis.this;
    }
    } public Inner inner(){
    return new Inner();
    } public static void main(String[] args) {
    DotThis dt = new DotThis();
    DotThis.Inner di = dt.inner();
    di.outer().f();
    } }

3.使用.new

  • 如果想要创建某个外部类的内部类,可以使用外部类对象.new 内部类:
  • 如果想new一个内部类, 不能使用外部类.new 内部类。必须使用外部类的对象来创建内部类的对象。    用法如下:
    package net.mindview.innerclasses;
    
    public class DotNew {
    
        public class Inner {
    
        }
    public static void main(String[] args) {
    DotNew dn = new DotNew();
    DotNew.Inner di = dn.new Inner();
    }
    }

4. 方法的内部类

  • 这里只说两点:

    • 方法的内部类有效作用域是在方法内,方法外部可以调用
    • 方法的内部类,并不是说方法被调用的时候才创建了,实际上,这个类和其他类没有什么不同,他们在使用之前,已经经过编译了.
      package net.mindview.innerclasses;
      
      /**
      * 方法内部类的作用域就在方法内,方法外不可以访问.
      * @author samsung
      *
      */
      public class Parcel5 {
      public Destination destination(String s){
      //在方法里定义了一个内部类
      class PDestination implements Destination{
      private String label;
      public PDestination(String label){
      System.out.println(this);
      this.label = label;
      }
      @Override
      public String readLabel() {
      return label;
      }
      } return new PDestination(s);
      }
      public static void main(String[] args) {
      Parcel5 p = new Parcel5();
      System.out.println(p.destination("上海").readLabel());
      System.out.println(p.destination("北京").readLabel());
      } /**
      * 注意:PDestination定义在方法里面,并不是说只有调用方法的时候,这个类才被创建.
      * 实际上,这个类和其他类一样,已经经过编译了.
      */
      }

5. 定义在作用域内的内部类, 此作用域在方法的内部.

  • 定义在方法作用域内部的类, 只在作用域内部有效
package net.mindview.innerclasses;

public class Parcel6 {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s){
id = s;
} String getSlip(){
return id;
}
} TrackingSlip ts = new TrackingSlip("");
String s = ts.getSlip();
}
//作用域外不可使用
//TrackingSlip ts = new TrackingSlip("100");
} public void track(){
internalTracking(true);
} public static void main(String[] args) {
Parcel6 p = new Parcel6();
p.track();
}
}

6.匿名内部类

  • 默认构造器匿名内部类

    package net.mindview.innerclasses;
    
    public class Parcel7 {
    public Contents contents(){
    //定义了一个匿名内部类.将返回值和创建类放在了一起
    return new Contents(){
    private int i = ;
    @Override
    public int value() {
    return i;
    }
    };
    }
    public static void main(String[] args) {
    Parcel7 p = new Parcel7();
    Contents c = p.contents();
    System.out.println(c.value()); } }
  • 代参数构造器的匿名内部类
    package net.mindview.innerclasses;
    
    public class Wrapping {
    
        private int i;
    public Wrapping(int x){
    this.i = x;
    }
    public int value(){
    return i;
    }
    }
    package net.mindview.innerclasses;
    
    public class Parcel8 {
    public Wrapping wrapping(int x){
    return new Wrapping(x){
    @Override
    public int value(){
    return super.value()*;
    }
    };
    } public static void main(String[] args) {
    Parcel8 p = new Parcel8();
    Wrapping w = p.wrapping();
    System.out.println(w.value());
    } }

    这里需要注意的是, 虽然Wrapping是一个导出类, 却依然被当成了一个接口来使用.

  • 匿名内部类中使用外部对象, 这外部的这个对象必须是final的
    package net.mindview.innerclasses;
    
    public class Parcel9 {
    public Destination destination(final String x){
    final String m = null;
    //匿名内部类
    return new Destination(){
    //在内部类中使用到了外部的对象
    private String label = m;
    private String abc = x;
    @Override
    public String readLabel() {
    return label;
    }
    };
    }
    public static void main(String[] args) {
    Parcel9 p = new Parcel9();
    System.out.println(p.destination("").readLabel());
    } /**
    * 定义一个匿名内部类, 如果希望在匿名内部类中使用外部的对象,
    * 那么编译器要求外部类的这个参数必须是final的. 如果你没有将这个类定义为final
    * 编译器会报错
    */ }
  • 在匿名内部类中使用类似构造器的行为. 我们知道匿名内部类没有类名, 因此他不可能有命名构造器. 但通过实例初始化可,就鞥够达到为匿名内部类创建一个构造器的效果
    package net.mindview.innerclasses;
    
    abstract class Base{
    public Base(int i){
    System.out.println("Base构造器, i=" + i);
    } public abstract void f();
    }
    public class AnonymousConstructor {
    /**
    * 此处的i不要求是final的,因为这个i只是传递给了匿名
    * 变量的构造器,并没有在匿名内部类内部使用.
    */
    public static Base getBase(int i){
    return new Base(i){
    {
    System.out.println("这里可以类似构造器进行初始化");
    }
    @Override
    public void f() {
    System.out.println("匿名函数f()");
    } };
    }
    public static void main(String[] args) {
    AnonymousConstructor amc = new AnonymousConstructor();
    amc.getBase().f();
    } }

7. 再谈工厂设计模式.

  再上一章中说了工厂设计模式. 本书中的案例是对象工厂设计模式. 来看看是怎么写的

package net.mindview.innerclasses.factory.MethodFactory;
/**
* 服务类
*/
interface Service{
void method1();
void method2();
} /**
* 工厂类
*/
interface ServiceFactory {
Service getService();
} class Implementation1 implements Service{ @Override
public void method1() {
System.out.println("Implementation1 method1");
} @Override
public void method2() {
System.out.println("Implementation1 method1");
} } class Implementation2 implements Service{ @Override
public void method1() {
System.out.println("Implementation2 method1");
} @Override
public void method2() {
System.out.println("Implementation2 method1");
} } class ImplementationFactory1 implements ServiceFactory{
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation1();
}
} class ImplementationFactory2 implements ServiceFactory{
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation2();
}
} public class Factories {
public static void serviceSustomer(ServiceFactory factory){
factory.getService().method1();
factory.getService().method2();
}
public static void main(String[] args) {
serviceSustomer(new ImplementationFactory1());
serviceSustomer(new ImplementationFactory2());
} }

  我们还可以将这种方式以内部类的方式来实现

package net.mindview.innerclasses.factory.methodFactoryInnerClass;
/**
* 服务类
*/
interface Service{
void method1();
void method2();
} /**
* 工厂类
*/
interface ServiceFactory {
Service getService();
} /**
* 每一种服务,提供一种工厂. 这种工厂专门创建这种服务.
*/
class Implementation1 implements Service{
private Implementation1(){}
@Override
public void method1() {
System.out.println("Implementation1 method1");
} @Override
public void method2() {
System.out.println("Implementation1 method1");
} //让工厂在内部实现
public static ServiceFactory factory = new ServiceFactory(){
@Override
public Service getService() {
return new Implementation1();
} }; } class Implementation2 implements Service{ @Override
public void method1() {
System.out.println("Implementation2 method1");
} @Override
public void method2() {
System.out.println("Implementation2 method1");
} //让工厂在内部实现
public static ServiceFactory factory = new ServiceFactory(){
@Override
public Service getService() {
return new Implementation2();
} }; } public class Factories {
public static void serviceSustomer(ServiceFactory factory){
factory.getService().method1();
factory.getService().method2();
}
public static void main(String[] args) {
serviceSustomer(Implementation1.factory);
serviceSustomer(Implementation2.factory);
}
}

  我的理解是: 第一种工厂的含义是: 我现在需要一种服务, 然后我找到对应的工厂, 为我提供服务. 工厂再去找对应这种服务的实体.

  而第二种方式呢, 我现在需要服务. 直接就去找这种服务对应的工厂就可以了. 也就是工厂内置了. 就像大公司下有多个子公司, 每个子公司都有自己的工厂.我要那种类型的东西,他就自己给生产了

8. 嵌套类

  如果内部类对象预期外围类对象之间不需要有联系, 那么可以将内部类声明为static的。这种累通常称为嵌套类。要想理解static定义的内部类的含义,就必须记住,普通的内部类对象隐式地保存了一个引用,指向创建他的外围类对象。然而,当内部类是static的时候, 就不是这样了。嵌套类意味着:

  1. 要创建嵌套类的对象, 并不需要外围类的对象。
  2. 不能从嵌套类的对象中访问非静态的对象
  3. 普通的内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以有这些东西
    package net.mindview.innerclasses;
    
    public class Parcel11 {
    //ParcelContent被定义为static的,所以是一个嵌套类
    private static class ParcelContent implements Contents {
    int i = ;
    @Override
    public int value() {
    return i;
    }
    } //ParcelDestination 是一个嵌套类. 被定义为static的.所以,它内部可以的有static的成员和方法
    private static class ParcelDestination implements Destination {
    private String label;
    private ParcelDestination(String label){
    this.label = label;
    }
    @Override
    public String readLabel() {
    return label;
    } public static void f(){
    System.out.println(AnotherLabel.x);
    //b()方法是访问不到的
    //AnotherLabel.b();
    }
    static int x = ;
    //他是嵌套在嵌套类内部的嵌套类.
    static class AnotherLabel{
    //内部定义了两个和外部一样的成员方法, 竟然不冲突
    public static void f(){
    System.out.println("这时静态类的静态方法");
    }
    static int x = ;
    //嵌套类中的非静态方法不能被外部访问到. 所以这个方法没有任何意义
    public void b(){
    System.out.println("这时静态类中的静态方法b()");
    }
    }
    } public static Contents getContents(){
    return new ParcelContent();
    } public static Destination getDestination(String s){
    return new ParcelDestination(s);
    } public static void main(String[] args) {
    System.out.println(getContents().value());
    System.out.println(getDestination("北京").readLabel()); //嵌套类中,不能访问非静态方法
    //ParcelDestination.readLabel();
    //但是可以方法静态方法
    ParcelDestination.f(); //嵌套类的使用方式是,类似于静态方法. 将其作为静态方法来使用.
    ParcelDestination.AnotherLabel.x=;
    System.out.println(ParcelDestination.AnotherLabel.x); ParcelDestination.AnotherLabel.f();
    //下面这样写是不对的
    //ParcelDestination.AnotherLabel.b();
    } }

    观看上面说的文字,会有些难以理解,所以, 将这段代码敲一遍,就理解什么意思了。动手很重要啊

9. 接口内部的类

  • 首先,接口里不能放置任何代码, 但是嵌套类可以.
  • 你放到接口中的任何类都自动式public static的.
  • 你可以在内部类中实现外围类的接口. 示例如下:
    package net.mindview.innerclasses;
    /**
    * 定义在接口内部的类
    */
    public interface ClassInInterface {
    void howdy();
    //这里static必须是显示标记出来的,否则这个类将不能运行
    static class Test implements ClassInInterface { @Override
    public void howdy() {
    System.out.println("Howdy!");
    } public static void main(String[] args) {
    Test t = new Test();
    t.howdy();
    }
    }
    }

    注意, 如果想运行main方法, 这里的嵌套类必须是static的.

  • 如果想创建某些公共代码, 使得他们可以被某个接口的所有实现类所共用, 那么使用接口内部的嵌套类会显得很方便.
  • 例如: 我们可以在每个类中写一个mian方法用来测试这个类, 这样做有一个缺点, 那就是要写好多遍,而且, 必须通过编译器的编译, 我们可以使用嵌套类改善
    package net.mindview.innerclasses;
    
    public class TestBed {
    public void f(){
    System.out.println("f()");
    } static class Testers{
    public static void main(String[] args) {
    TestBed t = new TestBedTest();
    t.f();
    }
    }
    }

    再说的白话一点,就是在接口中定义一个这样的嵌套类. 然后定义mian方法, 在main方法中使用嵌套类. 当有一个新的对象继承了这个类的时候, 就在这个类中的main方法进行测试就好了. 这样的好处是, 当我打包发布到正式环境的时候, 我想删除所有的main方法,因为他们的存在也会被编译器编译, 降低效率. 如果只有一个接口的嵌套类中定义的main方法,那么删起来就方便很多了。不明白的话,在看下面这个例子,就懂了

    package net.mindview.innerclasses;
    /**
    * 定义在接口内部的类
    */
    public interface ClassInInterface {
    void howdy();
    //这里static必须是显示标记出来的,否则这个类将不能运行
    static class Test implements ClassInInterface { @Override
    public void howdy() {
    System.out.println("Howdy!");
    } public static void main(String[] args) {
    //测试第一个实现了接口的类
    ClassInInterface t = new Test();
    t.howdy();
    //测试第二个实现了接口的类
    ClassInInterface t1 = new ClassInInterfaceTest();
    t1.howdy();
    }
    }
    }
    package net.mindview.innerclasses;
    
    public class ClassInInterfaceTest implements ClassInInterface{
    
        @Override
    public void howdy() {
    System.out.println("hhhh");
    }
    }
  • 接口中嵌套类如何创建实例化对象。 参考习题20
    package net.mindview.innerclasses.test20;
    interface InnerInInterface{
    static class Inner{
    public Inner(){
    System.out.println("嵌套类构造方法");
    }
    }
    } public class Test20 {
    public static void main(String[] args) {
    //直接使用 new 外围类.嵌套类
    InnerInInterface.Inner inner = new InnerInInterface.Inner();
    }
    }

10. 从多层嵌套类中访问外部类的成员

  注意下面这个例子是如何创建内部类的。

package net.mindview.innerclasses;
/**
* 多层嵌套类访问外部成员
*/ class A{
private void f(){};
class B{
private void b(){};
class C {
void c(){
f();
b();
};
}
}
}
public class MutliNestingAccess { public static void main(String[] args) {
A a = new A();
A.B b = a.new B();
A.B.C c = b.new C();
c.c();
} }

iooo

java编程思想第四版第十章总结的更多相关文章

  1. java编程思想第四版第十章习题

    第一题 package net.mindview.innerclasses; public class Outer { class Inner { Inner(){ System.out.printl ...

  2. java编程思想第四版中net.mindview.util包下载,及源码简单导入使用

    在java编程思想第四版中需要使用net.mindview.util包,大家可以直接到http://www.mindviewinc.com/TIJ4/CodeInstructions.html 去下载 ...

  3. 《Java编程思想第四版》附录 B 对比 C++和 Java

    <Java编程思想第四版完整中文高清版.pdf>-笔记 附录 B 对比 C++和 Java “作为一名 C++程序员,我们早已掌握了面向对象程序设计的基本概念,而且 Java 的语法无疑是 ...

  4. Java编程思想第四版勘误

    坊间传说这本书翻译得很烂,我倒觉得还好.虽然看原文更准确,但是如果在具备一定编程思维和基础.能够看出来疑问的情况下,还是看中文更快一些,而且这本书本身也不适合初学者看.当然,错误和不通顺还是有的,而且 ...

  5. Java编程思想第四版完整中文高清版.pdf

    Java编程思想第四版完整中文高清版.pdf 链接: https://pan.baidu.com/s/1vV5BHF3L-bnaG6WGurdJ_A 提取码: vigy 复制这段内容后打开百度网盘手机 ...

  6. 《Java编程思想第四版完整中文高清版.pdf》-笔记

    D.2.1 安插自己的测试代码 插入下述“显式”计时代码,对程序进行评测: long start = System.currentTimeMillis(); // 要计时的运算代码放在这儿 long ...

  7. 《Java编程思想第四版》附录 C Java 编程规则

    附录 C Java 编程规则 本附录包含了大量有用的建议,帮助大家进行低级程序设计,并提供了代码编写的一般性指导: (1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符 ...

  8. java编程思想第四版第九章总结

    1. 策略设计模式 参考这篇文章:http://blog.csdn.net/chenjie19891104/article/details/6396458 讲的很清楚,策略设计模式.并且举了一个例子, ...

  9. java编程思想第四版第十一章习题

    第一题 package net.mindview.holding.test1; import java.util.ArrayList; import java.util.List; /** * 沙鼠 ...

随机推荐

  1. PhantomJS not found on PATH

    使用vue-cli创建项目后,npm init常出现以下问题:PhantomJS not found on PATH 这是因为文件phantomjs-2.1.1-windows.zip过大,网络不好容 ...

  2. Kali Linux开启ssh服务设置自启

    几天没写 水一些今天遇到的问题 0x01 配置SSH参数 修改sshd_config文件,命令为:   vi /etc/ssh/sshd_config 将#PasswordAuthentication ...

  3. windows 7 专业版 64位 无法安装.Net 4.7版本解决方案

    什么暂停windows update,改文件夹,再恢复windows update等等方法都试了,不行之后就觉得这才是终极解决方案. 不管你是win 7什么版本,你只需要下载安装对应系统的Window ...

  4. [51nod1670] 打怪兽

    lyk在玩一个叫做“打怪兽”的游戏.游戏的规则是这样的.lyk一开始会有一个初始的能量值.每次遇到一个怪兽,若lyk的能量值>=怪兽的能量值,那么怪兽将会被打败,lyk的能量值增加1,否则lyk ...

  5. LeetCode初级算法--树01:二叉树的最大深度

    LeetCode初级算法--树01:二叉树的最大深度 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...

  6. MyCat教程二:mysql主从复制实现

      单个mysql数据库在处理业务的时候肯定是有限的,这时我们扩展数据库的第一种方式就是对数据库做读写分离(主从复制),本文我们就先来介绍下怎么来实现mysql的主从复制操作. 1. 读写分离   原 ...

  7. Go.js 没有中文文档 也没有中文demo 学起来很费劲 给大家整理一个算是详细的文档

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  8. 学习了解Shiro框架

    有关Shiro安全框架 实现权限的几种方式 1)通过表来实现 2)shiro框架 3)Spring Security框架 shiro有哪些主要功能 1.授权 访问控制的过程,即确定谁有权访问 2.身份 ...

  9. 基础安全术语科普(五)——crypter

    crypter(加壳):使病毒逃过反病毒软件检测的技术 UD类加壳病毒:只有%50至%25的软件能检测出是病毒. FUD类加壳病毒:完全不会被检测出来. 加壳技术有两个主要组件: 1.client — ...

  10. justjavac(迷渡)知乎live--<<前端工程师的入门与进阶>>听讲总结

    知乎听讲总结 知乎live----jjc<前端工程师的入门进阶> git地址 内容 前端的基础知识,计算机专业基础知识感觉还行.前端后台都有做过,现在觉得自己要深入.但是只看框架源码和自己 ...