首页 > 技术文章 > Java编程思想 (1~10)

liaojie970 2016-06-08 18:06 原文

【注:此博客旨在从《Java编程思想》这本书的目录结构上来检验自己的Java基础知识,只为笔记之用】

第一章 对象导论

1.万物皆对象
2.程序就是对象的集合
3.每个对象都是由其它对象所构成的
4.每个对象都拥有其类型
5.同一个类型的对象可以接收同样的消息

简单来说:对象具有状态,行为和标识

每个对象都是也给服务提供者,它通过使用其他对象提供的服务来完成自己服务

在Java语言中是单根继承

1.9 容器》java中指List,Map,Set
  1.91 参数化类型》泛型 eg:List<String> list=new ArrayList<String>();

1.10 对象的创建和生命周期》静态方式创建对象:在编写程序时就知道对象的确切数量,生命周期和类型,一般分配在堆栈或静态存储区域
动态方式创建对象:在堆(heap)的内存池中动态创建对象
在生命周期的控制上,在堆栈上创建对象的语言,编译器可以确定对象的存活时间并自动销毁,而在堆(heap)上创建对象,编译器
却不能正确的控制对象的生命周期。所以C++只能通过编程的方式来控制对象的生命周期,而Java因为提供了“垃圾回收机制”,它可以自动
的控制对象的销毁。
Java的这一能力主要得益于所有的对象都继承Object并且只能一种方式创建对象(在用new 在堆上创建)这两个特效

1.11异常处理:处理错误》Exception

1.12并发编程》共享资源

1.13Java和Internet》客户端/服务器 Javascript Actionscript 企业内部网(Intranet内联网)/互联网(Internet)

 

第二章
2.1 用引用操作对象》引用类型
2.2 必须由你创建所有对象》

  2.2.1 对象存储位置:寄存器(位于CPU内部);堆栈(为RAM随机访问存储器中); 堆(也位于RAM中); 常量存储(直接存储在
代码内部); 非RAM存储

  2.2.3 Java中的数组:当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会被自动初始化为null
            当创建一个基本数据类型的数组,也会在内存中全部初始化为零。

    public static void main(String[] args) {
        int[] test = new int[3];//基本数据类型数组
        for (int i : test) {
            System.out.println(i);
        }
        Integer[] tem = new Integer[3];//引用类型数组
        for (Integer integer : tem) {
            System.out.println(integer);
        }
    }

结果:

0
0
0
null
null
null

 

2.2.3 Java中的数组:当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会被自动初始化为null
当创建一个基本数据类型的数组,也会在内存中全部初始化为零。

2.32 对象的作用域:在Java中用new创建的对象,只要你需要就会一直保存下去;即便超出了它的作用域,但是因为它是
引用类型,所以它一直存在只是无法访问吧!至于防止内存溢出的问题,就是Java垃圾回收机制控制

2.4 创建新的数据类型:类
2.4.1 字段和方法

2.5 方法、参数和返回值
  2.5.1 参数列表
2.6 构建一个Java程序
  2.6.1 名字可见性》命名空间 ;域名反过来
  2.6.2 运用其他构件》import
  2.6.3 static关键字
2.7 你的第一个Java程序
  2.7.1 编译和运行
2.8 注释和嵌入式文档
  2.8.1 注释文档
  2.8.2 语法
  2.8.3 嵌入式HTML

 

  2.8.4 一些标签示例》@see引用其他类;{@link package.class#member label};{@docRoot};{@inheritDoc};@version;@anthor;@since
@param;@return;@throws;@deprecated

   /**
     * Returns the cause of this throwable or {@code null} if the
     * cause is nonexistent or unknown.  (The cause is the throwable that
     * caused this throwable to get thrown.)
     *
     * <p>This implementation returns the cause that was supplied via one of
     * the constructors requiring a {@code Throwable}, or that was set after
     * creation with the {@link #initCause(Throwable)} method.  While it is
     * typically unnecessary to override this method, a subclass can override
     * it to return a cause set by some other means.  This is appropriate for
     * a "legacy chained throwable" that predates the addition of chained
     * exceptions to {@code Throwable}.  Note that it is <i>not</i>
     * necessary to override any of the {@code PrintStackTrace} methods,
     * all of which invoke the {@code getCause} method to determine the
     * cause of a throwable.
     *示例:{@link #getClass()}
     * @return  the cause of this throwable or {@code null} if the
     *          cause is nonexistent or unknown.
     * @since 1.4
     */
    public synchronized Throwable getCause() {
        return (cause==this ? null : cause);
    }

  2.8.5 文档示例

2.9 编码风格》类名首字母大写 “驼峰命名法”

第三者 操作符
3.1 更简单的打印语句》System.Out.println("Hello word");
3.2 使用Java操作符》+ - * /
3.3 优先级
3.4 赋值
  3.4.1 方法调用中的别名问题》方法引用传参衍生出来的问题
3.5 算术操作符
  3.5.1 一元加、减操作符》++; --
3.6 自动递增和递减
3.7 关系操作符 》 >; < ;>=; <=
  3.7.1 测试对象的等价性
3.8 逻辑操作符》 “与(&&)”“或(||)”“非(!)”
  3.8.1 短路 》在与运算中第一个表达式为false整体为false,后面的表达式将不再执行;或运算中第一个表达式为true整
体为true,后面的表达式也不会在执行了。
3.9 直接常量
  3.9.1 指数记数法
3.10 按位操作符》 “&” “|” “&=”“|=”
3.11 移位操作符》“>>”“<<”“>>=”“<<=”“>>>=”
3.12 三元操作符》 exp1?exp2:exp3;
3.13 字符串操作符+和+=
3.14 使用操作时常犯的错误
3.15 类型转换操作符
  3.15.1 截尾和舍入
  3.15.2 提升》在做算术运算或按位运算时只要类型比int小,在运算前会自动转换成int;如果是float与double值相乘,结
果double;如果是int和long值相加,则结果为long.
3.16 Java没有sizeOf》因为Java才创建对象是不需要知道该类型的大小
3.17 操作符小结

第四章
4.1 true和false
4.2 if-else
4.3 迭代
  4.3.1 while和do-while
  4.3.2 for
  4.3.3 逗号操作符》for(exp1,exp2,....;判断表达式;exp3,exp4,.....)
4.4 Foreach语法
4.5 return
4.6 break和continue
4.7 臭名昭著的goto
4.8 switch》根据整数表达式的值,选择case分支去执行

第五章
5.1 用构造函数确保初始化
5.2 方法重载
  5.2.1 区分重载方法》重载方法的方法名相同,但是参数类型列表不同/参数顺序不同
  5.2.2 涉及基本类型的重载》传入的实际参数小于方法接受的基本类型参数,他就会被
自动提升满足该类型的参数,比如:方法f(int i),而传入的是short,那么实际参数就会 被转换为int;但是
如果传入的实际参数较大,那么必须手动执行类型转化
  5.2.3 以返回值区分重载方法》根据返回值区分重载是行不通的
5.3 默认构造函数》无参构造函数
5.4 this关键字
  5.4.1 在构造函数中调用构造函数
  5.4.2 static的含义》非静态方法可以调用静态方法;但是静态方法不能调用非静态方法
5.5 清理:终结处理和垃圾回收
  5.5.1 finalize()的用途何在》为了回收程序不再使用的内存
  5.5.2 你必须实施清理》如果Java虚拟机(JVM)并未面临内存耗尽的情况,它是不会浪费时
间去执行垃圾回收以恢复内存的
  5.5.3 终结条件
  5.5.4 垃圾回收器如何工作》与加载器操作有关的技术被称为"即时"(Just-In_Time,JIT)
编译器的技术。这种技术可以把程序全部或部分翻译成本地机器代码,程序的运行速度因此就会得到提升。
当需要装载某个类时,编译器会先找到其.class文件,然后将该类的字节码装入内存。此时,有两种方案:
第一种,让JIT编译所有代码,但是这种方式散落的加载动作会飞更多的时间;并且会增加肯可执行代码的长
度,从而降低程序速度
另一种方案:JIT只在必要的时候才编译代码;新版的JDK中的Java HotSpot技术就是采用类似的方法,代码每
次执行的时候都会做一些优化,所以执行的次数越多它的速度就越快

5.6 成员初始化
  5.6.1 指定初始化
5.7 构造器初始化
  5.7.1 初始化顺序
  5.7.2 静态数据的初始化
  5.7.3 显式的静态初始化》静态块;静态子句
  5.7.4 非静态实例初始化
5.8 数组初始化
  5.8.1 可变参数列表》在重载方法中最好不要使用可变参数或者只在一个版本上使用
5.9 枚举类型》enum

第六章 访问权限控制
6.1 包:库单元
  6.1.1 代码组织
  6.1.2 创建独一无二的包名
  6.1.3 定制工具库
  6.1.4 用import改变行为
  6.1.5 对使用包的忠告

6.2 Java访问权限修饰词
  6.2.1 包访问权限》默认访问权限没有任何关键字即包访问权限,包内其他类可见包外不可见
  6.2.2 public:接口访问权限
  6.2.3 private:你无法访问
  6.2.4 protected;继承访问权限
6.3 接口和实现
6.4 类的访问权限》限制:1.每个Java文件中只能有一个public类 2.public类的名称必须完全与Java文
件的文件名完全一样

第七章 复用类

7.1 组合语法
7.2 继承语法
  7.2.1 初始化基类
7.3 代理》代理模式
7.4 结合使用组合和继承
  7.4.1 确保正确清理
  7.4.2 名称屏蔽
7.5 在组合和继承之间选择
7.6 protected关键字
7.7 向上转型
  7.7.1为什么称为向上转型
  7.7.2再论组合和继承
7.8 final关键字
  7.8.1 final数据
  7.8.2 final方法》使用final方法的原因有两个:第一个原因是防止任何继承类修改该方法的定义;
第二个原因是效率,早期被声明为final的方法在编译时对该方法的调用都会转化为内嵌调用
  7.8.3 final类》当某个类被final修饰时表示该类不能被继承

  7.8.4 有final的忠告

7.9 初始化及类加载》类的代码在初次使用时才加载 即创建类的对一个对象时;尤其是在访问static成员时也会发生加载类代码
  7.9.1 继承与初始化

第八章 多态

8.1 再论向上转型
  8.1.2 忘记对象类型
8.2 转机
  8.2.1 方法调用绑定
  8.2.2 产生正确的行为
  8.2.3 可扩展性
  8.2.4 缺陷:"覆盖"私有方法》由于无法访问基类中的private方法,所以继承类也无法重载或覆写
基类中的private方法。所以在继承类中最好不要使用和基类private方法同名的名字
  8.2.5 缺陷:域与静态方法》只有普通方法调用可以多态

8.3 构造器和多态
  8.3.1 构造器的调用顺序
  8.3.2 继承与清理》在清理动手,可以交给Java的垃圾回收器;如果确实需要做特殊清理,那么可以自己定义方法,
调用该方法进行清理
  8.3.3 构造器内部的多态方法和行为》在编写构造函数是尽可能用简单的方法是对象进入正常状态;如果可以的
话,避免调用其它方法
8.4 协变返回类型》可以用基类类型去接收一个返回子类类型的方法返回值
8.5 用继承进行设计
  8.5.1 纯继承与扩展
  8.5.2 向下转型与运行类型识别

第9章 接口

9.1 抽象类和抽象方法
9.2 接口
interface Instructment{

  //编译时常量
  int VALUE=6;//static &final
  void play(int i);
  void adjust();
}

9.3 完全解耦
9.4 Java中的多重继承》一个类可以implements多个interface
9.5 通过继承来扩展接口》一个接口可以通过extends继承另一个接口
  9.5.1 组合接口时的名字冲突
9.6 适配接口
9.7 接口中的域
  9.7.1 初始化接口中的域
9.8 嵌套接口
9.9 接口与工厂

第十章

内部类的共性:
(1)内部类仍然是一个独立的类,编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号
(2)内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论
是否是private
(3)内部类声明成静态的,就不能随便的访问外部类的成员变量,此时内部类只能访问外部类的静态成员变量

10.1 创建内部类

        public class Parcel{
            class Contents{
                private int =1;
                public int value(){return i;}
            }
            //Using inner classes looks just like
            //using any other class,within parcel
            public c ship(){
                Contents c=new Contents();
                return c;
            }
            public static void main(String[] args){
                Parcel p=new Parcel();
                Parcel.Contents=p.ship();
            }
            
        }

10.2 链接到外部类》内部类自动拥有可以访问到外部类中的成员的

public class Sequence{
        private Object[] items;
        private int next=0;
        public Sequence(int size){
            items=new Object[size];
        }
        private class SequenceSelector{
            private int i=0;
            public boolean end(){
                return i=items.length;//
            }
            public void next(){
                i++;
            }
        }
        public SequenceSelector selector(){
            return new SequenceSelector();
        }
        
        public static void main(String[] args){
            Sequence seq=new Sequence();
            Sequence.SequenceSelector=seq.selector();
        }        
    }

10.3 使用.this与.new
在内部类中引用外部类对象,使用"外部类.this";创建某个内部类对象时需要使用外部类对象的引用+“.new”,使用形式"外部类对象.new"

    public class DotThis{
        void f(){}
        public class Inner{
            public DotThis outer(){
                return DotThis.this;
            }
        }
        public Inner inner(){return new Inner();}
        public static void main(String[] args){
            DotThis dt=new DotThis();
            DotThis.Inner dti=dt.new Inner();
            dti.outer().f();
        }
    }

在没有创建外部类对象前不能创建内部类对象的,因为内部类对象暗地里是关联到它的外部类对象上的。但是对于嵌套类(静态内部类),
就不需要对外部类对象的引用

10.4 内部类与向上转型

public interface Destination{
    String readLabel();
}
public interface Contents{
    int value();
}

class Parcel{
    private class PContents implements Contents{
        public int value(){return 10;}
    }
    
    protected class PDestination implements Destination{
        public String readLabel(){
            return "Hello word";
        }
    }
    
    public PContent contents(){
        return new PContents();
    }
    public PDestination destination(){
        return new PDestination();
    }
}
public class TestParcel{
    public static void main(String[] args){
        Parcel p=new Parcel();
        Contents c=p.contents();
        Destination d=p.destination();
    }
}

10.5 在方法和作用域内的内部类

//方法内部类(又称局部内部类)
public class Parcel{
    //方法
    public Destination destination(){
        //方法内部类
        class PInner implements Destination{
            public String say(){
                return "Hello word!";
            }
        }
        return new PInner();
    }
    
    public static void main(String[] args){
        Parcel p=new Parcel();
        Destination d=p.destination();
    }
}
//作用域内部类
public class Parcel{
    public void fun(boolean b){
        if(b){
            //作用域内部类
            class Inner{
                private String id;
                Inner(String id){
                    this.id=id;
                }
                public String say(){}
            }
            new Inner().say();
        }
    }
    public static void main(String[] args){
        Parcel p=new Parcel();
        p.fun(true);
    }
}

10.6 匿名内部类

abstract class Base{
        public Base(int i){
            print("Base constructor ");
        }
        public abstract void f();
    }
    public class Anonymous{
        public static Base getBase(int i){//这里的i参数传递给了匿名类的基类构造函数,
        //并没有在匿名类内部使用
            return new Base(i){
                public void f(){
                    print("Anonymout f()");
                }
            }
        }
        
        public Destination destination(final String dest,final float price){
            return new Destination(){
                private int cost;
                {
                    cost=Math.round(price);//当直接在匿名类直接使用参数时必须加final                    
                }
                private String str=dest;
            }
            
        }
        
        public static void main(String[] args){
            Base base=getBase(4);
            base.f();
        }
    }

  10.6.1在访工厂方法

interface Game{boolean move();}
interface GameFactory{Game getGame();}

class Checker implements Game{
    public boolean move(){...}
    public static GameFactory factory=new GameFactory(){
        public Game getGame(){return new Checker()};
    };
}
class Chess implements Game{
    public boolean move(){....}
    public static GameFactory factory=new GameFactory(){
        public Game getGame(){return new Chess()};
    };
}
public class TestGames{
    public static void playGame(GameFactory g){
        Game game=g.getGame();
        g.move();
    }
    
    public static void main(String[] args){
        playGame(Checker.factory);
        playGame(Chess.factory);
    }    
}

10.7 嵌套类
内部类声明为static就是嵌套类,与普通内部类的区别

(1)要创建嵌套类对象不需要外部类对象;

(2)不能从嵌套类的对象中访问非静态的外部类对象

(3)普通内部类不能有static数据和static字段

    class Outer{
        static class Inner{}
    }
    class Test {
        public static void main(String[] args){
            Outer.Inner n = new Outer.Inner();
        }
    }

  10.7.1 接口内部类

    public interface Outter{
        void fun();
        class Inner implements Outter{
            public void fun(){}
            public static void main(String[] args){
                new Inner().fun();
            }
        }
    }

  10.7.2 从多层嵌套类中访问外部类的成员》一个内部类被嵌套多少层并不重要,它都可以透明地访问所有它所嵌入的外部类的所有成员

class Outter1{
    private void f(){}
    class Outter2{
        private void g(){}
        class Inner{
            void h(){
                g();
                f();
            }
        }
    }    
}
public class Test{
    public static void main(String[] args){
        Outter1 o1=new Outter1();
        Outter1.Outter2 o2=o1.new Outter2();
        Outter1.Outter2.Inner i=o2.new Inner();
        i.h();
    }
}

10.8 为什么需要内部类
  10.8.1 闭包 

  闭包(closure)是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。通过这个定义可以看出在Java语言中,
内部类起着闭包的角色作用,因为它不仅包含了外部类对象创建内部类的作用域信息,还自动拥有一个指向此外部类对象的应用,
在此作用域内,内部类有权操作所有的成员,包括private成员。

package com.test.demo;

interface Incrementable {
    void increment();
}

class Callee1 implements Incrementable {
    private int i = 0;

    public void increment() {
        i++;
        System.out.println(i);
    }
}

class MyIncrement {
    public void increment() {// 注意这里已经有了一个increment方法
        System.out.println("\nOther operation");
    }

    static void f(MyIncrement mi) {
        mi.increment();
    }
}
//因为Callee2继承MyIncrement中已经又increment方法了
//如果Callee2想要implements(实现) Incrementable
//那么就需要使用内部类
class Callee2 extends MyIncrement {
    private int i = 0;

    public void increment() {
        super.increment();
        i++;
        System.err.println(i);
    }

    private class ClosureDe implements Incrementable {
        @Override
        public void increment() {
            Callee2.this.increment();//这里调用外部类的increment方法
        }
    }

    Incrementable getCallbackReference() {
        return new ClosureDe();
    }
}

class Caller {
    private Incrementable callbackreference;

    public Caller(Incrementable inc) {
        this.callbackreference = inc;
    }

    void go() {
        callbackreference.increment();
    }
}

public class Closure {
    public static void main(String[] args) {
        Callee1 c1 = new Callee1();
        Caller caller1 = new Caller(c1);
        caller1.go();
        caller1.go();

        Callee2 c2 = new Callee2();
        MyIncrement.f(c2);
        Caller caller2 = new Caller(c2.getCallbackReference());
        caller2.go();
        caller2.go();
    }
}

 

  10.8.2 内部类与控制框架
10.9 内部类的继承

package com.test.demo;
class WithInner {
class Inner {}
}

public class InheritInner extends WithInner.Inner {
  public InheritInner(WithInner wi) {
wi.super();
}
public InheritInner() {
new WithInner().super();
}
public static void main(String[] args) {
   WithInner wi = new WithInner();
   InheritInner ii = new InheritInner(wi);
  }
}

在继承内部类时如果继续使用默认构造器会报错,而且不能只传递一个指向外部类对象的引用。此时必须在构造器内使用如下语法:
  外部类对象.super();
这样才提供了必要的引用,才可以编译通过

10.10 内部类可以被覆盖吗》当继承某个外部类时,内部类并没有发生什么变化。内部类是完全独立的两个实体,各自在自己的命名空间内
10.11 局部内部类》局部内部类不能有访问说明符,因为它不是外部类的一部分;但是它可以访问当前代码代码块中的常量,以及此外部类的所有成员
10.12 内部类标识符》内部类也会生成一个.class文件。这些文件的命名规则是:外部类的名字+“$”+内部类的名字;如果是匿名内部类编译器也会产生一个数字作为你其标识

 

推荐阅读