Java从入门到精通(第2版)

龙马高新教育策划 魔乐科技软件实训中心编著 张玉宏主编

前言

  • 荀子曰:不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之。
  • 更多学习资料,请访问www.51pcbook.cn。
  • Java的跨平台性是指在一种平台下用Java语言编写的程序可以在编译后不用经过任何更改,就能在其他平台上运行。
  • 对于初(中)级程序员来说首先掌握Java的基本语法(如类与对象、构造方法、引用传递、内部类、异常、包、Java常用类库、Java IO及Java类集等)。
  • ⑴ 初级阶段:学习Java基础语法和类的创建与使用,基础I/O(输入/输出)操作、各种循环控制、运算符、数组的定义、方法定义格式、方法重载等,并熟练使用一种开发工具,如Eclipse等。⑵ 中级阶段:掌握面向对象的封装、继承和多态,学习常用对象和工具类,深入I/O(输入/输出)操作,异常处理、Java的包管理机制、集合框架等。⑶ 高级阶段:掌握Java的反射机制、泛型、网络编程、GUI开发、多线程、高级I/O、数据库编程、Java Applet等。

第1篇 基础知识

  • 环境变量是指在操作系统指定的运行环境中的一组参数,它包含一个或多个应用程序使用的信息。环境变量一般是多值的,即一个环境变量可以有多个值,各个值之间以英文状态下的分号“;”(即半角的分号)分隔开来。
  • Java程序运行的流程可用如右图来说明:所有的Java源代码(以.java为扩展名),通过Java编译器javac (javac命令中字母c来自于compiler的首字母)编译成字节码,也就是以.class为扩展名的文件。然后利用命令java将对应的字节码通过Java虚拟机(JVM)解释为特定操作系统(如Windows、Linux等)能理解的机器码,最终Java程序得以执行。
  • Java程序分为两种形式:一种是网页上使用的Applet程序(Java小程序),该程序可以嵌入在 HTML(标准通用标记语言的一个应用)页中。另一种是Application程序(即Java应用程序)

第3章 初识庐山真面目—Java程序要素概览

  • 在一个Java文件里,最多只能有一个public类,否则.java的文件便无法命名。
  • 的源码程序里,只能有一个public类,却可以有许多non-public(非公有)类。若是在一个Java程序中没有一个类是publ
  • Java的访问权限主要有4类:默认模式(default)、private(私有)、public(公有)和protected(保护)
  • 缓冲机制主要是为了处理应用程序和外设(输入/输出)之间速度不匹配的问题。
  • 用float型定义变量:float f = 3.14; 是否正确? (Java面试题)

第4章 最常用的编程元素—常量与变量

  • ⑴ 必须要在常量声明时对其进行初始化,否则会出现编译错误。常量一旦初始化后,就无法再次对这个常量进行赋值。⑵ final关键字不仅可用来修饰基本数据类型的常量,还可以用来修饰后续章节讲到的“对象引用”或者方法。
  • 只有加了static才能被main函数引用。
  • 声明一个变量时,编译程序会在内存里开辟一块足以容纳此变量的内存空间给它。不管该变量的值如何改变,都永远使用相同的内存空间。因此,善用变量是一种节省内存的方式。
  • 在类体中定义的变量为成员变量。它的作用范围为整个类,也就是说在这个类中都可以访问到定义的这个成员变量。
  • args主要用途是从命令行读取输入的参数
  • Java中作用范围是禁止嵌套的,而在C/C++中则是允许的
  • 局部变量在进行取值操作前必须被初始化或赋值操作

第5章 不可不知的数据分类法—数据类型

  • 每种基本的数据类型都有几个静态属性,如MAX_VALUE(最大值)、MIN_VALUE(最小值)、SIZE(大小)、TYPE(类型)等。要得到这些值,可用名称为该类型首字母大小对象(如byte类型对应Byte对象)通过点(.)操作符将其读取出来
  • int类型数据占据4个字节内存空间,取值范围为-2147483648 ~ 2147483647。
  • 数据最大值、最小值会出现一个循环过程,这种情况就称为数据溢出(overflow)。
  • double类型:共8个字节,64位,第1位为符号位,中间11位表示指数,最后52位为尾数。float类型:共4个字节,32位,第1位为符号位,中间8位表示指数,最后23位表示尾数。
  • 数据类型的转换方式可分为“自动类型转换”及“强制类型转换”两种
  • 而在Java中,由于boolean类型只能存放true或flase,与整数及字符不兼容,因此boolean类型不可能与其他任何数据类型进行转换。整数与浮点数亦是兼容的,所以可相互转换。
  • byte short int long float double,按照范围由小到大实现自动转型操作。
  • 而Java语言的布尔类型变量,其赋值只能是true(真)和false(假)两种。除此之外,没有其他的值可以赋值给布尔变量。也不能用1和0分别代替true(真)和false(假)。一言蔽之,Java语言中的布尔类型与整型无关。

第6章 最重要的编程部件—运算符、表达式与语句

  • Java的运算符可分为4类:算术运算符、关系运算符、逻辑运算符和位运算符。
  • Java中的取余操作数也可以是负数和浮点数,而在C/C++中,取余运算的操作数只能是整数。
  • 表达式是由常量、变量或是其他操作数与运算符所组合而成的语句
  • ⑴ 占用字节较少的数据类型转换成占用字节较多的数据类型。⑵ 字符类型会转换成int类型。⑶ int类型会转换成float类型。⑷ 表达式中若某个操作数的类型为double,则另一个操作数也会转换成double类型。⑸ 布尔类型不能转换成其他类型。
  • 空语句还可以用于在调试时留空以待以后添加新的功能。如果不是出于这种目的,一般不建议使用空语句,因为空语句不完成任何功能,但同样会额外占用计算机资源。
  • 位运算通常用于设置或获取标志位,及判断相应的操作是否成功。

第7章 程序执行方向—程序控制结构

  • 一般来说程序的结构包含以下3种。⑴ 顺序结构。⑵ 选择结构。⑶ 循环结构。
  • switch的表达式类型为整型(包括byte、short、char、int等)、字符类型及枚举类型。
  • foreach的语句格式。 for(元素类型type 元素变量var : 遍历对象obj) { 引用了var的Java语句; }
  • 其实习惯上如果if语句里只含有一条类似于break语句、continue语句或return语句的跳转语句,我们通常会省略if语句的大括号。
  • break语句不管情况如何,先离开循环再说;而continue语句则不再执行此次循环的剩余语句,而是直接回到循环的起始处。

第8章 常用的数据结构—数组

  • 在定义数组时不能在方括号中写下数组的长度,这点尤其需要初学者注意。
  • 不可以将null赋给基本类型变量(如int、float、double等)。

第9章 面向对象设计—类和对象

  • 将具有相同属性及相同行为的一组对象称为类(class)。
  • 言,构造方法(constructor,又称构造器或构造函数
  • 属性名应该由一个或多个有意义的单词(或能见名知意的简写)连缀而成,推荐的风格是第一个单词应以小写字母作为开头,后面的单词则用大写字母开头,其他字母全部小写,单词间不使用其他分隔符。
  • 被static修饰的变量称为类变量(class's variables),它们被类的实例所共享。也就是说,某一个类的实例改变了这个静态值,其他这个类的实例也会受到影响。而成员变量(member variable)则是没有被static修饰的变量,为实例所私有,也就是说,每个类的实例都有一份自己专属的成员变量,只有当前实例才可更改它们的值。
  • 对象只有在实例化之后才能被使用,而实例化对象的关键字就是new。
  • 所谓的匿名对象就是指,只开辟了堆内存空间,而没有栈内存指向的对象
  • “==”运算符用于比较两个对象的内存地址值(引用值)是否相等,equals()方法用于比较两个对象的内容是否一致。
  • 在这里需要读者记住,“==”是比较对象内存地址值(即所谓的引用值)的,而“equals”是比较对象内容的。
  • 由于this是和对象本身相关联的,所以this只能在类中的非静态方法中使用。静态属性及静态方法属于类,它们与具体的对象无关,所以静态属性及静态方法是没有this的

第10章 重复调用的代码块—方法

  • 构成方法有四大要素。返回值类型、方法名称、参数、方法体。
  • 这种使用方法名相同但参数列表不同的方法签名机制,称之为方法的重载(method overload)。
  • 在读者自定义设计重载方法时,读者需要注意以下3点,这些重载方法之间。⑴ 方法名称相同。⑵ 方法的参数列表不同(参数个数、参数类型、参数顺序,至少有一项不同)。⑶ 方法的返回值类型和修饰符不做要求,可以相同,也可以不同。
  • 方法的签名仅包括方法名称和参数,因此方法重载不能根据方法的不同返回值来区分不同方法,因为返回值不属于方法签名的一部分。
  • 构造方法是在一个对象实例化的时候只调用一次的方法,而普通方法则可通过一个实例化对象调用多次。正是因为构造方法的特殊性,它才有特殊的语法规范
  • 在Java程序中一旦用户显式声明了构造方法,那么默认的“隐式的”构造方法就不会被编译器生成。
  • 如果构造方法被设为private,那么其他类中就无法调用该构造方法。换句话说,在本类之外,就不能通过new关键字调用该构造方法创建该类的实例化对象。
  • 在软件工程中,这种设计模式被称之为单态设计模式(Singleton Design Pattern)。
  • 递归是指函数(或方法)直接或间接调用自身的一种操作
  • 递归程序一定要有结束条件,这又被称作递归出口
  • 代码块有四种。⑴ 普通代码块。⑵ 构造代码块。⑶ 静态代码块。⑷ 同步代码块。
  • 构造代码块就是在类中直接定义的,且没有任何前缀、后缀以及修饰符的代码块。
  • 构造代码块和构造方法一样是在对象生成时被调用,但是它的调用时机比构造方法还要早。
  • 构造代码块不在任何方法之内,仅位于类的范围内,它的地位和其他方法体是对等的,可以理解为构造代码块是没有名称的方法体,但仅限用于对类数据成员的初始化,且仅运行一次。
  • 使用static关键字加以修饰并用大括号“{ }”括起来的代码块称为静态代码块,其主要用来初始化静态成员变量。它是最早执行的代码块。
  • 静态代码块的执行时间主方法main()方法都要早。静态块还优先于构造方法的执行,而且不管有多少个实例化对象产生(本例中创建了3个对象),静态块都只执行一次。

第11章 快速归类整型常数—枚举

  • 使用public static final这三个关键字来作为所创建对象的修饰符,表明这三个对象是“公有的、静态的、不可更改的”常量对象。
  • allof()是EnumSet中的内部静态方法,用来将这个方法参数中所指向的全部内容设置到集合。
  • Java语言虽然不支持一个类有多个直接的父类(即不支持多继承),但一个类却可以实现(implements)多个接口。
  • 定义枚举类型时,如果是简单类型,那么最后一个枚举值后可以不加分号。但是如果枚举中包含有方法,那么最后一个枚举值后面代码必须要用分号“;”隔开。

第2篇 核心技术

  • 封装 (Encapsulation)是将描述某类事物的数据与处理这些数据的函数封装在一起,形成一个有机整体,称为类。
  • 使用super关键字加上对应的参数,就是调用父类的构造方法
  • 在Java中只允许单继承,而不允许多重继承,也就是说一个子类只能有一个父类。但在Java中允许多层继承。
  • 限制4:被final修饰的类不能再被继承。
  • 子类对象在实例化时,子类对象实例化会默认先调用父类中的无参构造函数,然后再调用子类构造方法。
  • 由此可以证明子类对象在实例化时会默认先去调用父类中的无参构造方法,之后再调用本类中的相应构造方法。
  • 如用户显式用super()去调用父类的构造方法,那么它必须出现在这个子类构造方法中的第1行语句
  • super主要的功能是完成子类调用父类中的内容,也就是调用父类中的属性或方法。
  • 调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有提供这种形式的构造方法,那么在编译的时候就会报错。
  • super关键字不仅可用于调用父类中的构造方法,也可用于调用父类中的属性或方法
  • 这种创建无名对象的方式只能临时创建一个对象,使用一次后即自动销毁了。
  • 当一个子类继承一个父类,如果子类中的方法与父类中的方法的名称、参数个数及类型且返回值类型等都完全一致时,就称子类中的这个方法覆写了父类中的方法。
  • ⑴ 覆写的方法的返回值类型必须和被覆写的方法的返回值类型一致;⑵ 被覆写的方法不能为static。
  • ⑴ 覆写的方法的返回值类型必须和被覆写的方法的返回值类型一致; ⑵ 被覆写的方法不能为static。
  • 从开发角度来说,为了满足类的封装型,类中的属性一般都需要使用private封装,一旦封装之后,子类压根就“看不见”父类的属性成员,子类定义的同名属性成员,其实就是一个“全新的”数据成员,所谓的覆写操作就完全没有意义了。
  • ⑴ 向上转型可以自动完成。⑵ 向下转型必须进行强制类型转换。
  • 简单来说,继承是子类使用父类的方法,而多态则是父类使用子类的方法。但更为确切来说,多态是父类使用被子类覆盖的同名方法,如果子类的方法是全新的,父类不存在同名的方法,则父类也不能使用子类自己独有的“个性化”方法。
  • 隐藏(Hide)。被关键词static修饰的静态方法是不能被覆盖的, Java就是利用这一个特性达到隐藏的效果。
  • 重载是指在相同类内定义名称相同但参数个数或类型或顺序不同的方法,而覆写是在子类当中定义名称、参数个数与类型均与父类相同的方法,用于覆写父类中的方法。

第13章 抽象类与接口

  • 抽象方法是只声明而未实现的方法,所有的抽象方法必须使用abstract关键字声明,包含抽象方法的类也必须使用abstractclass声明。
  • 与一般类相同,在抽象类中也可以拥有构造方法,但是这些构造方法必须在子类中被调用,并且子类实例化对象的时候依然满足类继承的关系,先默认调用父类的构造方法,而后再调用子类的构造方法,毕竟抽象类之中还是存在属性的,只不过这个抽象方法无法直接被外部实例化对象的时候所使用。
  • ⑶ 在外部抽象类上无法使用static声明,但是内部抽象类却可以使用static定义,使用static定义的内部抽象类就表示一个外部类。
  • ⑷ 抽象类之中可以没有抽象方法,但即便没有抽象方法的抽象类也不能够直接在外部通过关键字new实例化。
  • 接口里的数据成员必须初始化,且数据成员均为常量,常见的是全局变量。
  • Java8中允许在接口中只定义默认方法,无抽象方法。
  • 接口与抽象类相比,最大的区别就在于子类上,子类可以同时实现多个接口。
  • 因此,一个类实现多个接口时,若接口中有默认方法,不能出现同名默认方法。
  • 接口使用过程中,一个抽象类可以继承多个接口,但是反过来讲,一个接口却不能够继承抽象类,但是一个接口却可以使用extends关键字继承多个接口。
  • 代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用。
  • 在程序员自己开发的代码之中,只要是遇见了取得接口对象实例的操作,都应该采用工厂设计模式。
  • 代理设计模式的核心组成:一个接口有两个子类,一个子类负责真实的业务操作功能,另外一个子类负责完成与真实业务有关的操作。
  • 抽象类和接口不同点。⑴ 抽象类不可以多重继承,接口可以(无论是多重类型继承还是多重行为继承);⑵ 抽象类和接口所反映出的设计理念不同。其实抽象类表示的是"is-a"关系,接口表示的是"like-a"关系;⑶ 接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值;抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

第14章 关于类的专题研究

  • equals(),此方法用于比较对象是否相等,而且此方法必须被覆写。
  • 在用equals对两个对象进行比较时,实际上是比较两个对象的地址。
  • 在默认情况下equals()方法用来比较两个对象的地址值,而原始的hashCode()方法用来返回其所在对象的物理地址。
  • 在覆写equals()方法的时候也必须覆写hashCode()方法。这样才能确保相等的两个对象拥有相等的.hashCode。
  • 内部类主要有如下作用。⑴ 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。⑵ 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以相互访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。⑶ 匿名内部类适合用于创建那些仅需要一次的类。
  • static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。
  • 匿名内部类不能是抽象类,所以必须要实现它的抽象父类或者接口里面所有的抽象方法。
  • 匿名内部类存在一个缺陷,就是它仅能被使用一次,创建匿名内部类时它会立即创建一个该类的实例,该类的定义会立即消失,所以匿名内部类不能够被重复使用。
  • this表示当前对象,而所谓的当前对象就是指调用类中方法或属性的那个对象。
  • 在使用static类型声明的方法时需要注意的是,如果在类中声明了一个static类型的属性,则此属性既可以在非static类型的方法中使用,也可以在static类型的方法中使用。若要用static类型的方法调用非static类型的属性,就会出现错误。
  • 一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行,且只执行一次。静态代码块经常用来进行类属性的初始化。
  • ⑴ final标记的类不能被继承。⑵ final标记的方法不能被子类覆写。⑶ final标记的变量(成员变量或局部变量)即为常量,只能赋值一次。
  • 可以用instanceof判断一个类是否实现了某个接口,也可以用它来判断一个实例对象是否属于一个类

第15章 储存类的仓库—Java常用类库

  • 所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质
  • 装箱操作:将基本数据类型变为包装类,利用各个包装类的构造方法完成;拆箱操作:将包装类变为基本数据类型,利用Number类的xxxValue()方法完成。
  • 在将字符串变为数值型数据时需要注意,字符串的组成必须全部由数字组成。
  • (1) 任何的基本数据类型遇见String之后自动变为字符串。(2) 利用String类之中提供的一系列valueOf()方法完成。
  • System类中的所有成员都是静态的,而要引用这些变量和方法,可直接使用System类名作为前缀。
  • exit(int status)方法,提前终止虚拟机的运行。对于发生了异常情况而想终止虚拟机的运行,传递一个非零值作为参数。若在用户正常操作下终止虚拟机的运行,则传递零值作为参数。

第16章 解读Java中的String类

  • String类对象的内容一旦被初始化就不能再改变,对于String类的每次改变(例如字符串连接等)都会生成一个新的字符串,比较浪费内存。
  • equalsIgnoreCase( )可以忽略大小写的进行两个字符串的比较。
  • 运算符==比较两个对象是否引用同一个实例。

第17章 对象的引用与传递

  • 在Java中对于方法参数的传递,对象是传递引用,基本数据类型是传递值。
  • Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
  • 不管有多少个子类,工厂类都可以使用,这就是反射机制所带来的好处,而在日后的开发之中,如果发现有时候需要写出完整的“包.类”,就表示此处使用了反射机制。
  • 框架开发原理 = 反射机制 + XML解析。
  • 虽然Java之中提供了垃圾的自动回收机制,但是考虑到性能的问题,还是建议操作的过程之中尽量少产生垃圾为好。

第18章 包及访问权限

  • 若在不同的package中存在相同类名的public类,若要访问某个public类的成员时,在程序代码内必须明确地指明“被访问package的名称.类名称”。
  • 如果一个成员方法或成员变量名前面使用了protected访问控制符,那么这个成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问。

第19章 异常的捕获与处理

  • 我们把生成异常对象并把它提交给运行时系统的过程称之为异常的抛出(throw)。运行时系统在方法的调用栈中查找,从生成异常的方法开始进行回溯,直到找到包含相应异常处理的方法为止,这一过程称之为异常的捕获(catch)。
  • 请解释Exception和RuntimeException的区别?· Exception:强制性要求用户必须处理;· RuntimeException:是Exception的子类,由用户选择是否进行处理。
  • 异常类型的最大父类是Throwable类,其分为两个子类,分别为Exception、Error。Exception表示程序可处理的异常,而Error表示JVM错误,一般无需程序开发人员自己处理。

第20章 Java类集框架

  • 需要为多个对象排序时必须设置排序规则,而排序规则就可以通过比较器进行设置,而在Java之中比较器提供了两种:Comparable和Comparator。

第3篇 高级应用

  • 多线程“同时”执行是给人的一种感觉,而实际上在线程之间轮换执行,只不过多个线程之间切换的延迟足够短,给人的感觉好像是在同时执行一样。
  • 设置为某个线程为守护线程时,一定要在start()方法调用之前设置,也就是说一个线程启动之前设置其属性