读后笔记 -- Java核心技术(第11版 卷I )Chapter3 Java 的基本程序设计结构

 Java 语言规范: https://docs.oracle.com/javase/specs/

3.2. 注释

Java 注释类型:

1)单行注释:
 // like this

2)多行注释(不能嵌套):
/*
    like
    this
*/

3)文档注释:
/**
 * This is the first sample program in Core Java
 * @version 1.0 2002/1/1
 * @author Gary Cornell
 */

3.3 数据类型

Java 8种基本数据类型(Java 是强类型语言)
整型

int :      4字节     -2 147 483 648 ~ 2 147 483 647 (刚好超过 20 亿)

short:   2字节     -32 768 ~ 32 767

long:    8字节     -9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807

byte:    1字节     -128 ~ 127

L/l:              长整型      0x/0X:         十六进制

0b/0B:         二进制      1_000_000:  数字加下划线,表示100万 

* 八进制不建议用,数字前加0,容易混淆

浮点类型

float:      4字节    大约 ± 3.402 823 47E+38F (有效位数为 6 ~ 7 位)

double:  8字节    大约 ± 1.797 693 134 862 315 70E+308 (有效位数为 15 位)

 

F/f:               float类型 (很少使用,除非某些方法要求

D/d:              double类型(没有F后缀,默认类型

特殊常量

1)Double.POSITIVE_INFINITY, Double_NEGATIVE_INFINITYDouble.NaN ,

     实际很少遇到,可使用: if(Double.isNaN(x))   // check whether x is "not a number"

 

2)System.out.println(2.0-1.1) 将打印 0.8999999999999999,因为二进制系统表示浮点数值

     导致的舍入误差。如计算中不允许有任何舍入误差,应使用 BigDecimal 类

char 类型 

char 类型的字面量值要用 '' 括起来,如 'A'

可表示为十六进制,其范围从 \u0000 ~ \Uffff

特殊字符的转义序列:(转义序列 -- Unicode值)

\b--\u0008     \t--\u0009    \n--\u000a     \r--\u000d

\''--\u0022      \'--\u0027    \\--\u005c 

** 当心注释中的 \u ,如: // Look inside c:\users => 编译失败

// \u000A is a new line => 编译失败,读程序时,\u000A 已经转为换行符。

Unicode 转义序列会在解析代码之前得到处理。

boolean 类型 true, false 

整数值和布尔值之间不能相互转换

如 if (x = 0) // oops... meant x ==0,c++可编译运行,其结果总是false,而java不能编译 

3.4 变量

3.4.1 变量初始化

  • 声明后,必须显式初始化;
  • 声明尽可能靠近第一次使用的地方(良好习惯);
  • 不区分变量的声明与定义【C/C++区分定义和声明:   int i = 10; //定义       extern int i; //声明 】;

注意

  • 1)大小写敏感;
  • 2)不提倡一行声明多个变量;

3.4.2 常量

  • final:     该变量只能被赋值一次;常量名使用全大写。
  • static final:类常量,定义位于 main 方法的外部
  • public:       一个常量被声明为 public,其他类的方法也可以使用这个常量
public class Constants2 {
    public static final double CM_PER_INCH = 2.54;    // final:常量,static final:类常量(被一个类中的多个方法使用)

    public static void main(String[] args){
        double paperWidth = 8.5;
        double paperHeight = 11;
        System.out.println("Paper size in centimeters:"  + paperWidth * CM_PER_INCH + " by " + paperHeight * CM_PER_INCH) ;
    }
}

3.5 运算符

3.5.1  /0 的结果:

  • 整数 除以 0 => 异常;
  • 浮点数 除以 0 => 无穷大 或 NaN

3.5.3  类型转换

  • 实线数据无损
  • 虚线有可能精度损失

 当用一个二元运算符连接两个值时,将向表示更大数值的类型进行转换。 double > float > long > int

long n = 100;
float ff = 200;
float hh = n + ff;     // long hh = ff + n; => error

3.5.4  强制类型转换

double x = 9.997;
int nx = (int) x;                // 强制转换,nx = 9
int nx = (int) Math.round(x);    // 对浮点进行舍入运算, nx =10。因为 round 返回的是 long 类型,所以需要 (int) 显式强转   

3.5.6  自增/减

int m = 7;
int n = 7;
int a = 2 * ++m;     // now a is 16, m is 8 => 先更新变量值,再计算
int b = 2 * n++;     // now b is 14, n is 8 => 先计算,再更新变量值
// ** 不建议在表达式中使用 ++/--
优先级 运算符分类 结合顺序 运算符

分隔符 左结合 .   []   (方法调用 )   ;  ,
一元运算符 右结合 !  ++  --  -  ~

算术运算符

移位运算符

左结合 *  /  %  +   -  <<  >>  >>>
关系运算符 左结合 <  >  <=  >=  instanceof(Java 特有)  = =  !=
逻辑运算符 左结合 !  &&  ||  ~("not")  &("and")  |("or")  ^("xor") 
三目运算符 右结合 布尔表达式?表达式1:表达式2
赋值运算符 右结合 =  *=   /=  %=  +=  -=  <<=  >>=  >>>=  &=  *=  |=

*** 不确定优先级时,用 () 来处理

5. 枚举

// 自定义枚举类型
enum Size (SMALL, MEDIUM, LARGE, EXTRA_LARGE };
// 声明该类型的变量
Size s = Size.MEDIUM;

3.6 字符串

  • substring: 子串;  
  • +:              拼接;  
  • .join():  使用定界符拼接字符串; String all = String.join(" / ", "S", "M", "L", "XL");   // all: "S / M / L / XL"
  • equals() / equalsIgnoreCase:检测两个字符串是否相等(区分/不区分大小写)。
  • !! equals:比较值
  •    ==: 比较对象地址
// 3.6.5 空串与 null 串
"" :空串;        // str1 = "";    str1.length() => 0
nullnull 串    // str1 = null;  str1.length() => NullPointerException

if (str.length() == 0) 或 if (str.equals(""))     // 1)空串 
if (str == null)                                 // 2)null;
if (str != null && str.length() != 0)             // 3)字符串不是 null 也不是空串
// 3.6.6 码点与代码单元
// 1. 字符串 转 码点数组
int[] codePoints = str.codePoints().toArray();

// 2. 码点数组 转 字符串
String str = new String(codePoints, 0, codePoints.length);
// 3.6.9 String 类对象是不可变的(immutable),所以需要有一个类(Stringbuilder)来处理如键盘输入的场景
// step1: 构建一个空的字符串构建器
StringBuilder builder = new StringBuilder();
// step2: 添加内容 builder.append(ch); builder.append(str);
// step3:构建字符串 String completedString = builder.toString();

3.7 输入输出

Scanner in = new Scanner(System.in);    // 它有4个有用的方法: nextLine, next, nextInt, nextDouble
// 接受字符串
String name = in.nextLine();
// 接受数值
int age = in.nextInt();
printf 的转换符,如:System.out.printf("%,.2f", 10000.0 / 3.0);   // 3333.33
转换符 类型 举例   转换符 类型 举例
d
十进制整数
159   s
字符串
Hello
x
十六进制整数
9f   c
字符
H
o
八进制整数
237   b
布尔
True
f
定点浮点数
15.9   h
散列码
42628b2
e
指数浮点数
1.59e+01 
 
tx 或 Tx
日 期 时 间
(T 强制大写) 
已经过时, 应当改为使用
javaJime 类,参见卷 II 第 6章
g
通用浮点数
  %
百分号
%
a
十六进制浮点数
0xl.fccdp3
  n
与平台有关的行分隔符

 

printf 的 标志,如: Systtem.out.prinf("%(,.2f", -1000.0 / 3.0)    // (3333.33)
标 志
目 的 举 例   标 志 目 的 举 例
+
打印正数和负数的符号
+3333.33
  , 添加分组分隔符 3,333.33 
空格
在正数之前添加空格
| 3333.33|
  # ( 对于 f 格式) 包含小数点 3,333. 
0
数字前面补 0
003333.33 
  # (对于 x 或 0 格式) 添加前缀 Ox 或 0 Oxcafe 
-
左对齐
13333.33 |
 
给定被格式化的参数索引。例如, %l $d,%l$x 
将以十进制和十六进制格式打印第 1 个参数
 
159 9F 
(
将负数括在括号内 
( 3333.33 )
 
格式化前面说明的数值。 例如,%d%<X 以十进制和
十六进制打印同一个数值
159 9F 
System.out.printf("%,.2f", 10000.0 / 3.0);

System.out.printf("%8.2f", 10000.0 / 3.0);===== output ====
3,333.33   // 1)保留小数点2位;2)千分位;3)实际位数
 3333.33   // 1)保留小数点2位;2)包含小数点8位,不足的补空格

3.7.2  格式化:

  1)参数格式化

// %1$:是对后面的第1个参数格式化, %2$:对第2个参数(new Date())的结果格式化,以 t 开始 + 日期/时间的转换符
// 索引 从 1 开始 System.out.printf(Locale.ENGLISH, "%1$s %2$tB %2$te, %2$tY", "Due date: ", new Date()); // Due date: December 21, 2021

  2)Use String.format if you don't want to print:

String message = String.format("Hello, %s. Next year, you'll be %d", name, age);

  3)格式说明符

 

3.7.3 文件输入输出

// 读取文件
// // in Java 7 and 10, we need to use Paths.get(); after later version, we should use Path.of()
Scanner in = new Scanner(Path.of("C:\\test.robot"), StandardCharsets.UTF_8);

// 写入文件
PrintWriter out = new PrintWriter("myfile.txt", StandardCharsets.UTF_8);
out.println(...);

// Need to tag main like this:
public static void main(String[] args) throws IOException {
    Scanner in = new Scanner(Path.of("C:\\test.robot"), StandardCharsets.UTF_8);
    ...
}
// 一个有用的方法,获取当前目录
String dir = System.getProperty("user.dir");

3.8 控制流程

!!不能在嵌套的两个块中声明同名的变量
public static void main(String[] args) {
    int n; 
    {
        int k;
        int n; // Error -- can't redefine n in inner block
    } 
}

3.8.2  if (condition) statement

3.8.3  while

  • while (condition) statement
  • do statement while (condition);      // 1)do 至少执行一次;  2)后面有一个 “;”

3.8.4  for (int i = 1; i <= 10; i++)

  • 1)如要使用最终的值,需在 for 循环外部定义。 int i;     for (i = 1; i <= 10; i++)
  • 2)for 循环中 不要使用 浮点数

3.8.5 switch(较少使用)

  • 1)每个 case 后面需要跟一个 break; 否则会一直往下执行
  • 2)case 标签可以是:
  •       类型为 char、byte、short 或 int 的常量表达式;
  •       枚举常量;
  •       字符串字面量(Java SE 7 开始);

3.9 大数

  • BigInteger:实现任意精度的整数运算;
  • BigDecimal:实现任意精度的浮点数运算;【相对比较常用,float 因为有精度问题】
BigDecimal bigDecimal1 = new BigDecimal("0.1");
BigDecimal bigDecimal2 = new BigDecimal(0.1);

// 输出 0.1 => 方式: 1)new BigDecimal("str"), 2)使用 BigDecimal.valueOf(0.1);
System.out.println("bigDecimal1: " + bigDecimal1);
// 输出 0.1000000000000000055511151231257827021181583404541015625
System.out.println("bigDecimal2: " + bigDecimal2);

 * 不能使用 +,* 计算,换成 add,multiply

BigInteger lotteryOdds = BigInteger.valueOf(1);
for (int i = 1; i < k; i++) {
    lotteryOdds = lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i));
}

3.10 数组

数组:存储相同类型值的序列。

3.10.1  声明

int[] a = new int[100];    // var a = new int[100];

数组初始化:

  • 1)数字数组,初始化值 0;
  • 2)boolean数组,初始化值 false;
  • 3)对象数组(如字符串数组),初始化值 null;

数组创建后,不能改变大小(array.length())。如运行过程中可扩展数组,则使用另外一个数据结构 array list

 

数组初始化及匿名数组

// 1)初始化数组
int[] smallPrimes1 = {2, 3, 5, 7, 11, 13};

// 2):new int[] {,,}:初始化一个匿名数组,然后赋值给另一个数组 
int[] smallPrimes2 = new int[] {17, 19, 23, 29, 31, 37};

//初始化一个长度为 0 的数组
new int[0]

 

3.10.3  for each 循环(泛型 for 循环): for (variable : collection) statement

        int[] a = new int[20];
        for (int i = 0; i < 20; i++) {
            a[i] = i;
        }

        // 方式一:传统 for 循环打印
        for (int i = 0; i < 20; i++) {
            System.out.println(a[i]);
        }

        // !!! 方式二:for each 打印
        for (int num : a){
            System.out.println(num);
        }

        // 方式三:Arrays.toString 方式打印
        System.out.println(Arrays.toString(a));

 

3.10.4  数组 copy 及排序 sort

// 数组排序(无论是 数值数组 还是 字符串 数组)
Arrays.sort(luckyNumbers);
public class CopiedArray {
    public static void main(String[] args) {
        int[] smallPrimes = {2, 3, 5, 7, 11, 13};
        // 1)(浅copy,“=”)指向同一个地址,修改内容时,两个数组都被改
        int[] luckyNumbers = smallPrimes;

        luckyNumbers[2] = 6;

        // smallPrimes: [2, 3, 6, 7, 11, 13]
        System.out.println("smallPrimes: " + Arrays.toString(smallPrimes));
        // luckyNumbers: [2, 3, 6, 7, 11, 13]
        System.out.println("luckyNumbers: " + Arrays.toString(luckyNumbers));

        // 2)(深copy,"Arrays.copyOf()")复制数组,相对独立,修改一个时,不影响另外一个
        //     另外,第二个参数为长度 < 原数组长度:引用指定的数据; =:全复制; >:多余的补默认值
        int[] copiedLuckyNumbers = Arrays.copyOf(smallPrimes, smallPrimes.length);
        copiedLuckyNumbers[0] = 100;

        // smallPrimes: [2, 3, 6, 7, 11, 13]
        System.out.println("smallPrimes: " + Arrays.toString(smallPrimes));
        // copiedLuckyNumbers: [100, 3, 6, 7, 11, 13]
        System.out.println("copiedLuckyNumbers: " + Arrays.toString(copiedLuckyNumbers));
    }
}

 

3.10.7   二维数组

// 1.1 声明二维数组
double[][] balances;
// 1.2 初始化二维数组
balances = new double[NYEARS][NRATES];
// 2. 初始化二维数组,如果知道数组元素,则不需要 new int[][] magicSquares = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} } // 打印二维数组。for each 循环不能自动处理二维数组的每一个元素。需要使用两个嵌套的循环 for (double[] row : balances) { for (double b : row) { System.out.printf("%10.2f", b); } System.out.println(); }

// 快速打印二维数组的数据,可以用
System.out.println(Arrays.deepToString(balances));

 

3.10.8 不规则数组

    当需要不规则的数组时,只能单独地创建行数组

final int MAX = 10;

// allocate triangular array
// 1)定义不规则数组的最大行
int[][] odds = new int[NMAX + 1][];

for (int n = 0; n <= NMAX; n++) {
    // 2)定义每行的数组长度
    odds[n] = new int[n +1];
}

 

posted on 2021-12-16 11:40  bruce_he  阅读(160)  评论(0编辑  收藏  举报