Java核心技术卷一基础知识第10版学习笔记收录
如果需要相关书籍可以私信我或者在下面评论.
第二章 JAVA程序设计环境
2.2 常用DOS命令
- 盘符切换 ----------具体盘符:+回车(eg:E:+enter)
- 查询文件夹下所有的文件----------adk+回车
- 进入某个文件夹---------cd+空格+文件夹名称
- 单级回退---------cd…
- 多级回退 ----cd+空格+
2.3 利用JDK运行eclipse创建的JAVA项目
如果JDK安装正确且环境变量配置成功了,就不要轻易怀疑错误了。编译和运行出错可能是路径错误。
文件所创建的路径:windows(窗口)---Preferences(偏好)---然后看图
1.编译:找到.java项目创建的文件夹进行编译。ps:正确路径是到包含.java后缀名的文件夹
2.运行:正确路径是到包含.java后缀名的文件夹的文件夹
第三章 JAVA的基本程序设计结构
3.1一个简单的Java应用程序
System,out.println("Hello"); //输出后会自动换行再进行输出
System,out.print("Hello");//)打印“ Hello” 之后不换行, 后面的输出紧跟在字母o之后
在这里,使用了 System.out 对象并调用了它的 println 方法。注意, 点号( • )用于调用方法。Java 使用的通用语法是object.method(parameters)这等价于函数调用。
3.2注释
/* */注释不允许嵌套使用
3.3数据类型
在 Java 中, 所有的数值类型所占据的字节数量与平台无关。在 C 和 C++ 中,int 和 long 等类型的大小与目标平台相关。
3.3.1整型
3.3.2浮点型
float 类型的数值有一个后缀 F 或 f (例如,3.14F。) 没有后缀 F 的浮点数值(如 3.14 ) 默
认为 double 类型。
具体来说,下面是用于表示溢出和出错情况的三个特殊的浮点数值:
•正无穷大
•负无穷大
•NaN (不是一个数字)
例如, 一 正整数除以 0 的结果为正无穷大。计算 0/0 或者负数的平方根结果为 NaN。
3.5运算符
3.5.1数学函数与常量
Math.sqrt();//开平方,返回double
Math.pow(a,b);//计算a的b次幂,返回double
Math.PI;//Π
Math.E;//e
Math.round();//四舍五入取整数,返回long
3.5.2数值类型之间的转换
3.5.8括号和运算符级别
3.6字符串
3.6.1字串
String greeting = "Hello";
String s = greeting.substring®, 3);
substring 方法的第二个参数是不想复制的第一个位置。这里要复制位置为 0、 1 和 2 (从 0 到 2, 包括 0 和 2 ) 的字符。在 substring 中从 0 开始计数,直到 3 为止, 但不包含 3。
3.6.2拼接
int age = 13;
String rating = "PC" + age;
System.out.println("The answer is " + rating);
//如果需要把多个字符串放在一起, 用一个定界符分隔,可以使用静态 join 方法:
String all = String.join(" / ", "S", "M", "L", "XL");
// all is the string "S / H / L / XL"
3.6.3不可变字符串(字符串常量)
为了弄清具体的工作方式,可以想象将各种字符串存放在公共的存储池中。字符串变量
指向存储池中相应的位置。如果复制一个字符串变量, 原始字符串与复制的字符串共享相同
的字符。
3.6.4检测字符串是否相等
s.equals(t);//如果字符串 s 与字符串 t 相等, 则返回 true ; 否则, 返回 false。
string greeting="Hello";
"Hello".equals(greeting);
//要想检测两个字符串是否相等,而不区分大小写, 可以使用 equalsIgnoreCase 方法。
"Hello".equalsIgnoreCase("hel1o");
一定不要使用==运算符检测两个字符串是否相等! 这个运算符只能够确定两个字串
是否放置在同一个位置上。
如果虚拟机始终将相同的字符串共享, 就可以使用=运算符检测是否相等。但实际上
只有字符串常量是共享的,而 + 或 substring 等操作产生的结果并不是共享的。
3.6.5空串与Null串
空串是一个 Java 对象, 有自己的串长度( 0 ) 和内容(空)。不过, String 变量还可以存
放一个特殊的值, 名为 null, 这表示目前没有任何对象与该变量关联。
有时要检查一个字符串既不是 null 也不为空串,这种情况下就需要使用以下条件:
if (str != null && str.length() != 0)
3.6.8阅读联机文档
文档地址https://docs.oracle.com/javase/8/docs/api/
3.6.9构建字符串
//首先, 构建一个空的字符串构建器:
StringBuilder builder = new StringBuilder();
builder.append(ch); // appends a single character
bui1der.append(str); // appends a string
String completedString = builder.toString();
3.7输入与输出
3.7.1读取输入
//Scanner类包含在java.util.Scanner中
Scanner inScanner=new Scanner(System.in);//构造一个 Scanner 对象,并与“ 标准输人流” System.in 关联
String string1=inScanner.nextLine();//nextLine 方法将输入一行,换行符作为输入结束标志
String string2=inScanner.next();//读取一个单词,空白符作为分隔符
int intNum=inScanner.nextInt();//读取一个整数
double doubleNum=inScanner.nextDouble();//读取一个浮点数
3.7.2格式化输出
时间输出:格式包括两个字母, 以 t 开始, 以表 3-7 中的任意字母结束。
3.8控制流程
3.8.5多重选择:switch语句
case 标签可以是:
•类型为 char、byte、 short 或 int 的常量表达式。
•枚举常量。
•从 Java SE 7开始, case 标签还可以是字符串字面量。
3.8.6中断控制流程语句
这里有一个示例说明了 break 语句的工作状态。请注意,标签必须放在希望跳出的最外
层循环之前, 并且必须紧跟一个冒号。
Scanner in = new Scanner(System.in);
int n;
read_data://标签!
while (. . .) // this loop statement is tagged with the label
for (. . .) // this inner loop is not labeled
{
Systen.out.print("Enter a number >= 0: "); n = in.nextlntO;
if (n < 0) // should never happen-can’t go on
break read.data; // break out of readjata loop
}// this statement is executed immediately after the labeled break
//!!!跳转到这里,下面用于检测是否为正常结束
if (n < 0) // check for bad situation
{ // deal with bad situation
}
else
{ // carry out normal processing
}
如果输入有误,通过执行带标签的 break 跳转到带标签的语句块末尾。对于任何使用
break语句的代码都需要检测循环是正常结束, 还是由 break 跳出。
事实上,可以将标签应用到任何语句中, 甚至可以应用到 if语句或者块语句中。
另外需要注意, 只能跳出语句块,而不能跳入语句块。
3.9大数值
包含的包
import java.math.*;
//Biglnteger 类实现了任意精度的整数运算, BigDecimal 实现了任意精度的浮点数运算。
//使用静态的 valueOf方法可以将普通的数值转换为大数值:
BigInteger a=BigInteger.valueOf(10);
BigInteger b=BigInteger.valueOf(10);
//使用大数值类中的 add 和 multiply 方法
BigInteger integer2=a.add(b);//相加
BigInteger integer=a.multiply(b.add(BigInteger.valueOf(100)));//integer=a*(b+100)
3.10数组
3.10.1 foreach循环
3.10.2数组初始化以及匿名数组
3.10.3数组拷贝
3.10.4数组排序
第四章 对象与类
4.1面向程序设计概述
4.1.4类之间的关系
在类之间, 最常见的关系有
•依赖(“ uses-a”)
•聚合(“ has-a”)
•继承(“ is-a”)
依赖( dependence ), 即“ uses-a” 关系, 是一种最明显的、 最常见的关系。例如,Order类使用 Account 类是因为 Order 对象需要访问 Account 对象查看信用状态。但是 Item 类不依赖于 Account 类, 这是因为 Item 对象与客户账户无关。因此, 如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少。如果类 A 不知道 B 的存在, 它就不会关心 B的任何改变(这意味着 B 的改变不会导致 A 产生任何 bug )。用软件工程的语来说,就是让类之间的耦合度最小。
聚合(aggregation ), 即“ has-a ” 关系, 是一种具体且易于理解的关系。例如, 一个Order 对象包含一些 Item 对象。聚合关系意味着类 A 的对象包含类 B 的对象。
4.2使用预定义类
4.2.1对象与对象变量
在对象与对象变量之间存在着一个重要的区别。例如, 语句
Date deadline; // deadline doesn't refer to any object
定义了一个对象变量 deadline, 它 可 以 引 用 Date 类型的对象。但是,一定要认识到: 变量deadline 不是一个对象, 实际上现在它也没有引用对象。此时,不能将任何 Date 方法应用于这个变量上。
必须首先初始化变量 deadline, 这里有两个选择。
- 当然,可以用新构造的对象初始化这个变量:
deadline = new Date();
- 也可以让这个变量引用一个已存在的对象:
deadline = birthday;
一定要认识到: 一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。
在 Java 中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new 操作符的返回值也是一个引用。下列语句:
Date deadline = new Date();
有两个部分。表达式 new Date() 构造了一个 Date 类型的对象, 并且它的值是对新创建对象的引用。这个引用存储在变量 deadline 中。
可以显式地将对象变量设置为null 表明这个对象变量目前没有引用任何对象。
deadline = null;
4.2.2Java中的LocalDate类
4.3用户自定义类
4.3.2 多个源文件的使用
带有main方法的类必须声明为公有的,因为文件名必须与public的名字匹配,
在一个源文件中, 只能有一个公有类,但可以有任意数目的非公有类。
总共有两种方法
- 使用通配符调用 Java编译器:
javac Employee*.java
,于是,所有与通配符匹配的源文件都将被编译成类文件。 - 或者键人下列命令:
javac EmployeeTest.java
使用第二种方式,并没有显式地编译 Employee.java 然而,当 Java 编
译器发现 EmployeeTest.java 使用 Employee 类时会查找名为 Employee.class 的文件。如果没有找到这个文件, 就会自动地搜索 Employee.java, 然后,对它进行编译。更重要的是:如果 Employee.java 版本较已有的 Empl0yee.dass 文件版本新,Java 编译器就会自动地重新编译这个文件。
但是我没搞懂这两个方式,我自己摸索出来了,反正能用。
- 两个类在不同的包里
要求类是公有类,不是会报错。然后
import 包名.类名;
- 两个类在同一个包里
不要求类是公有类
import 包名.类名;
4.3.5隐式参数与显示参数
在 Java 中, 所有的方法都必须在类的内部定义, 但并不表示它们是内联方法。是否将某个方法设置为内联方法是 Java 虚拟机的任务。即时编译器会监视调用那些简洁、经常被调用、 没有被重载以及可优化的方法。
4.3.6封装的优点
警告: 注意不要编写返回引用可变对象的访问器方法。
出错的原因很微妙。d 和 harry.hireDay 引用同一个对象(请参见图 4-5 )。
更改器方法就可以自动地改变这个雇员对象的私有状态!
如果需要返回一个可变对象的引用, 应该首先对它进行克隆(clone )。
return (Date) hireDay.cloneO; // OK
凭经验可知, 如果需要返回一个可变数据域的拷贝,就应该使用 clone。
4.4静态域与静态方法
4.4.3静态方法
静态方法是一种不能面向对象施加操作的方法。换句话说没有隐式的参数。静态方法不能访问实例域,因为它不能操作对象。但是静态方法可以访问自身类中的静态域。
在下面两种情况下使用静态方法:
•一 方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如:Math.pow)
•一个方法只需要访问类的静态域(例如:Employee.getNextldh)
4.5方法参数
这个过程说明:Java 程序设计语言对对象采用的不是引用调用,实际上, 对象引用是按值传递的。
下面总结一下 Java 中方法参数的使用情况:
•一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
•一个方法可以改变一个对象参数的状态。
•一个方法不能让对象参数引用一个新的对象。
4.6对象构造
4.6.3无参数的构造器
如果在编写一个类时没有编写构造器, 那么系统就会提供一个无参数构造器。这个构造器将所有的实例域设置为默认值。于是, 实例域中的数值型数据设置为 0、 布尔型数据设置为 false、 所有对象变量将设置为 null。
如果类中提供了至少一个构造器, 但是没有提供无参数的构造器, 则在构造对象时如果没有提供参数就会被视为不合法。
注:类似C++提供一个默认构造函数,有了构造函数默认的构造函数就不会被提供。
4.6.4显式域初始化
可以在类定义中, 直接将一个值赋给任何域。例如:
class Employee{
private String name ="";
}
在执行构造器之前,先执行赋值操作。当一个类的所有构造器都希望把相同的值赋予某个特定的实例域时,这种方式特别有用。
初始值不一定是常量值。在下面的例子中, 可以调用方法对域进行初始化。仔细看一下Employee 类,其中每个雇员有一个 id 域。可以使用下列方式进行初始化:
class Employee
{
private static int nextld;
private int id = assignldO;
private static int assignldO
{
int r = nextld;
nextld++;
return r;
}
}
注:类似C++的初始化参数列表
4.6.5参数名
public Employee(String aNaie, double aSalary) {
name = aName ;
salary = aSalary; }
public Employee(String naie, double salary) {
this.name = name;
this,sal ary = salary;
}
4.6.6调用另一个构造器
关键字 this 引用方法的隐式参数。然而,这个关键字还有另外一个含义。
如果构造器的第一个语句形如 this(…), 这个构造器将调用同一个类的另一个构造器。下面是一个典型的例子:
public Employee(double s) {
// calls Employee(String, double)
this("Employee #" + nextld, s);
nextld++;
}
采用这种方式使用 this 关键字非常有用, 这样对公共的构造器代码部分只编写一次即可。
4.6.7初始化块
在一个类的声明中,可以包含多个代码块。只要构造类的对象,这些块就会被执行。
将代码放在一个块中,并标记关键字 static。在类第一次加载的时候, 将会进行静态域的初始化。
4.7包
4.7.1类的导入
- 第一种方式是在每个类名之前添加完整的包名。
java.tine.LocalDate today = java.tine.Local Date.now();
- 可以使用 import 语句导人一个特定的类或者整个包。import 语句应该位于源文件的顶部(但位于 package 语句的后面)。`import java.util .*;
4.7.4包作用域
标记为 public 的部分可以被任意的类使用;标记为 private 的部分只能被定义它们的类使用。如果没有指定 public 或 private , 这 个 部分(类、方法或变量)可以被同一个包中的所有方法访问。
第五章 继承
5.1类、超类和子类
5.1.2覆盖方法
public double getSalaryO
{
double baseSalary = getSalaryO;// still won't work
return baseSalary + bonus;
}
上述语句调用的是 Employee 类中的 getSalary 方法。
下面是 Manager 类中 getSalary 方法的正确书写格式:
public double getSalaryO
{
double baseSalary = super.getSalaryO*
return baseSalary + bonus;
}
5.1.3 子类构造器
由于 Manager 类的构造器不能访问 Employee 类的私有域, 所以必须利用 Employee 类的构造器对这部分私有域进行初始化,我们可以通过 super 实现对超类构造器的调用。使用super 调用构造器的语句必须是子类构造器的第一条语句。
如果子类的构造器没有显式地调用超类的构造器, 则将自动地调用超类默认(没有参数 )的构造器。 如果超类没有不带参数的构造器, 并且在子类的构造器中又没有显式地调用超类的其他构造器,则 Java 编译器将报告错误。
一个对象变量(例如, 变量 e ) 可以指示多种实际类型的现象被称为多态( polymorphism)。在运行时能够自动地选择调用哪个方法的现象称为动态绑定( dynamic binding。)
5.1.5多态
有一个用来判断是否应该设计为继承关系的简单规则, 这就是“is-a” 规则, 它表明子类的每个对象也是超类的对象。 每个经理都是雇员, 因此, 将Manager 类设计为 Employee 类的子类是显而易见的,反之不然, 并不是每一名雇员都是经理。
“ is-a” 规则的另一种表述法是置换法则。它表明程序中出现超类对象的任何地方都可以用子类对象置换。
- 可以将一个子类的对象赋给超类变量。
Employee e;
e = new Employee(. . .); // Employee object expected
e = new Manager(. . .); // OK, Manager can be used as well
- 在这个例子中,变量 staff[0] 与 boss[0]引用同一个对象。但编译器将 staff[0]看成 Employee 对象。
Manager boss = new Manager(. . .);
Employee[] staff = new Employee[3];
staff[0] = boss;
boss.setBonus(5000); // OK
staff[0].setBonus(5000); // Error
这是因为 staff[0] 声明的类型是 Employee, 而 setBonus 不是 Employee 类的方法。
- 在 Java 中,子类数组的引用可以转换成超类数组的引用, 而不需要采用强制类型转换。
Manager[] managers = new Manager[10];
EmployeeQ staff = managers; // OK
样做肯定不会有问题, 请思考一下其中的缘由。 毕竟, 如果 manager[i] 是一个Manager, 也一定是一个 Employee。然而, 实际上,将会发生一些令人惊讶的事情。要切记 managers 和 staff 引用的是同一个数组。
staff[0] = new Employee("Harry Hacker", . . .);
但在这里, stafflO] 与 manager[0] 引用的是同一个对象, 似乎我们把一个普通雇员擅自归入经理行列中了。这是一种很忌伟发生的情形,当调用 managers[0].setBonus(1000) 的时候, 将会导致调用一个不存在的实例域, 进而搅乱相邻存储空间的内容。
例如, 使用 new managers[10] 创建的数组是一个经理数组。如果试图存储一个 Employee 类型的引用就会引发 ArrayStoreException 常。
5.1.6理解方法调用
下面是调用过程的详细描述:
1 ) 编译器査看对象的声明类型和方法名。假设调用 x.f(param,) 且隐式参数 x 声明为 C类的对象。需要注意的是:有可能存在多个名字为 f, 但参数类型不一样的方法。例如,可能存在方法 f(im) 和方法 String。) 编译器将会一一列举所有 C 类中名为 f 的方法和其超类中访问属性为 public 且名为 f 的方法(超类的私有方法不可访问)。
至此, 编译器已获得所有可能被调用的候选方法。
2 ) 接下来,编译器将査看调用方法时提供的参数类型。如果在所有名为 f 的方法中存在一个与提供的参数类型完全匹配,就选择这个方法。这个过程被称为重栽解析( overloading resolution)。例如,对于调用 x.f(“ Hello” )来说, 编译器将会挑选 f(String,) 而不是 f(int)。由于允许类型转换( int 可以转换成 double, Manager 可以转换成 Employee, 等等,) 所以这个过程可能很复杂。如果编译器没有找到与参数类型匹配的方法, 或者发现经过类型转换后有多个方法与之匹配, 就会报告一个错误。至此, 编译器已获得需要调用的方法名字和参数类型。
3 ) 如果是 private 方法、 static 方法、 final 方法(有关 final 修饰符的含义将在下一节讲述)或者构造器, 那么编译器将可以准确地知道应该调用哪个方法, 我们将这种调用方式称为静态绑定( static binding )。 与此对应的是,调用的方法依赖于隐式参数的实际类型, 并且在运行时实现动态绑定。在我们列举的示例中, 编译器采用动态绑定的方式生成一条调用 f (String) 的指令。
4 ) 当程序运行,并且采用动态绑定调用方法时, 虚拟机一定调用与 x 所引用对象的实际类型最合适的那个类的方法。假设 x 的实际类型是 D,它是 C 类的子类。如果 D 类定义了方法 f(String,) 就直接调用它;否则, 将在 D 类的超类中寻找 f(String,) 以此类推。
注:没看太明白~~~》。。。《
5.1.7阻止继承:final类和方法
- 注释:前面曾经说过, 域也可以被声明为 final。 对于 final 域来说,构造对象之后就不允许改变它们的值了。不过, 如果将一个类声明为 final, 只有其中的方法自动地成为 final,而不包括域。
5.1.9抽象类
使用 abstract 关键字,为了提高程序的清晰度, 包含一个或多个抽象方法的类本身必须被声明为抽象的。
public abstract class Person
{
public abstract String getDescription();
}
除了抽象方法之外,抽象类还可以包含具体数据和具体方法。例如, Person 类还保存着姓名和一个返回姓名的具体方法。
public abstract class Person
{
private String name;
public Person(String name)
{
this.name = name ;
}
public abstract String getDescription();
public String getName()
{
return name;
}
}
抽象方法充当着占位的角色, 它们的具体实现在子类中。扩展抽象类可以有两种选择。
一种是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就必须将子类也标记为抽象类;
另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。
注:类似C++的纯虚函数。
类即使不含抽象方法,也可以将类声明为抽象类。抽象类不能被实例化。也就是说,如果将一个类声明为 abstract, 就不能创建这个类的对象。
但可以创建一个具体子类的对象。需要注意, 可以定义一个抽象类的对象变量, 但是它只能引用非抽象子类的对象。
Person p = new Student("Vinee Vu" , "Economics");
这里的 p 是一个抽象类 Person 的变量,Person 引用了一个非抽象子类 Student 的实例。
5.1.10受保护修饰符
例如,如果将超类 Employee中的 hireDay 声明为 proteced, 而不是私有的, Manager 中的方法就可以直接地访问它。
不过,Manager 类中的方法只能够访问 Manager 对象中的 hireDay 域, 而不能访问其他Employee 对象中的这个域。
粗略浏览的内容
- 位运算符
- 码点与代码单元
- 文件输入与输出
- 类路径