Java 学习笔记 | 注释 & 基本数据类型 & 变量 & 运算符

Java 9 REPL (JShell)

REPL(Read-Evaluate-Print-Loop) —— 交互式解释器环境
意为: 读取-计算-打印循环
其流程为:输入值,交互式解释器会读取输入内容并对它求值,再返回结果,并重复此过程

JShell 是 Java 9 引入的一个 REPL 工具,其为 Java 提供了一个交互式的编程环境工具

Note!在Java Core 2.4 节第一次看到的,觉得 JShell 非常方便,就写在这里了!

Java 注释

Java 注释分为三种:

  1. 单行注释:// 开头,// 之后的内容都会被注释掉。
    // 这是一个单行注释
    
  2. 多行注释:/* 开头,以 */ 结尾,之间的内容都会被注释掉。
    /*
     * 这是一个多行注释
     * 这是一个多行注释
     * 这是一个多行注释
     * 中间的 '*' 只是为了好看一些而被大家遵守的约定 
     */
    
  3. JavaDoc 注释: 文档注释,以 /** 开头,以 */ 结尾,可以在之间写一些描述性的信息,帮助 javadoc 生成 API 帮助文档。
    /**
     * @author:作者
     * @version 版本
     * @since 最小支持的 JDK 版本
     * @see 参考转向(相关主题)
     * @docroot:表示产生文档的根路径
     * @deprecated:不推荐使用的方法
     * @param 方法参数类型
     * @return 方法返回类型
     * @exception 对方法可能抛出的异常进行描述(推荐描述 Runtime 异常)
     * @throws 对方法可能抛出的异常进行描述(推荐描述 非 Runtime 异常)
     */
    

Note!一些有趣的代码注释可以搜索有趣的代码注释

基本数据类型

Java 是一种强类型语言,这意味着必须为每一个变量声明一种类型

Java 的数据类型

Java data type
Note!Java 确定了每种基本类型的内存占用大小,这些大小不会像其他一些语言那样随着机器环境的变化而变化。这种不变性也是 Java 更具可移植性的一个原因。
Note!基本类型变量不是使用 new 创建变量,而是使用一个 “自动” 变量,这个变量直接存储 “值(Value)”,并置于栈内存中,因此更加高效。

数字

JDK 7 之后,数字间可以用下划线 _ 分隔,提高可读性。

jshell> int num1 = 123_456;
num1 ==> 123456

jshell> long num2 = 123_3454355_345L;
num2 ==> 1233454355345

jshell> byte num3 = 1_20;
num3 ==> 120

jshell> float num4 = 123_63724_2.24F;
num4 ==> 1.2363724E8

jshell> double num5 = 12_34.45;
num5 ==> 1234.45

整数

Note!在创建 long 型整数时,为避免小写 l 与数字 1 混淆,推荐在数字后跟大写 L。例:long num = 10L;

  • 十进制表示:正常表示
    jshell> int num = 10;
    num ==> 10
    
  • 二进制表示:二进制以 0b 开头,后面跟二进制数
    jshell> int num = 0b10;
    num ==> 2
    
  • 八进制表示:八进制以 0 开头,后面跟八进制数
    jshell> int num = 010;
    num ==> 8
    
  • 十六进制表示:十六进制以 0x 开头,后面跟十六进制数
    jshell> long num = 0x10L;
    num ==> 16
    

浮点数

Note!在创建 float 型浮点数时,为与 long 保持统一,推荐在数字后跟大写 F。例:float num = 10.12345F;
Note!在创建浮点数变量时,如果数字后没有跟 Ff 后缀,则默认为 double 类型。如下:

jshell> float num = 10.12345;
|  错误:
|  不兼容的类型:double转换到float可能会有损失
|  float num = 10.12345;
|              ^-----^

浮点数存在精度问题,最后避免使用浮点数进行比较!

jshell> float num1 = 1F;
num1 ==> 1.0

jshell> double num2 = 1;
num2 ==> 1.0

jshell> num1 == num2
$3 ==> true
--------------------------
jshell> float num3 = 0.1F;
num3 ==> 0.1

jshell> double num4 = 0.1;
num4 ==> 0.1

jshell> num3 == num4
$6 ==> false

Note!在涉及银行或其它对精度要求特别高的业务时,使用 BigIntegerBigDecimal(大数处理工具类) 进行处理。
Note!在 Java 中有两种类型的数据可用于高精度的计算。它们是 BigIntegerBigDecimal
BigInteger 支持任意精度的整数,可用于精确表示任意大小的整数值,同时在运算过程中不会丢失精度。
BigDecimal 支持任意精度的浮点数

字符型(char)

char 类型原本用于表示单个字符char 类型的字面量值要用单引号括起来。

jshell> char ch1 = 'A'; // 'A' 是编码值为 65 的字符常量
ch1 ==> 'A'

Note!'A'"A" 不同,'A' 是字符常量,"A" 是包含一个字符 A 的字符串。

char 类型的大小为 2 个字节,它的值可以表示为十六进制值范围从 \u0000\uFFFF

jshell> char ch1 = '\u2122'; // \u2122 表示商标符号 ™
ch1 ==> '™'

jshell> char ch2 = '\u03C0'; // \u03C0 表示希腊字母 π
ch2 ==> 'π'
Unicode 和 char 类型

Java 使用的字符集是 Unicode 字符集。
前面说 char 类型(2个字节)原本用于表示单个字符,但由于现在 Unicode 字符集的不断扩充,2 个字节已经不足以表示后来扩充的一些字符了,需要用 3 个或 4 个甚至更多字节来表示一些字符。
事实上,现在 Java 中的 char 类型描述的是 UTF-16 编码中的一个代码单元
Java 语言所使用的用来对 Unicode 字符集进行编码的编码方式正是 UTF-16
UTF-16 编码方式同时结合了定长和变长两种编码方法的特点,要么是 2 个字节,要么是 4 个字节。也就是说,现在在 Java 中要表示一个字符,可能需要 1 个 char,也可能需要 2 个 char

Note!关于 Unicode 和 char 的关系请参考我的另一篇博客:Java 中 Unicode 和 char 的关系

jshell> "a人".length()
$1 ==> 2

jshell> "a人".codePointCount(0, 2)
$2 ==> 2

jshell> "𠋥".length()
$3 ==> 2

jshell> "𠋥".codePointCount(0, 1)
$4 ==> 1

jshell> "𠋥".codePointAt(0)
$5 ==> 131813

jshell> Integer.toHexString(131813)
$6 ==> "202e5"

Note!强烈建议不要在程序中使用 char 类型,除非确实需要处理 UTF-16 代码单元。
最好将字符串(String)作为抽象数据类型处理。

特殊字符的转义序列
转义序列名称Unicode值
\a响铃-
\b退格\u0008
\f换页,将当前位置移到下页开头-
\t制表\u0009
\v垂直制表-
\n换行\u000A
\r回车\u000D
\"双引号\u0022
\’单引号\u0027
\\反斜杠\u005C
\0空字符\u0000
\ddd1到3位八进制数所代表的任意字符三位八进制
\xhh1到2位十六进制所代表的任意字符两位十六进制

Note!所有转义序列都可以出现在加引号的字符字面量或字符串中,只有转义序列 \u 还可以出现在加引号的字符字面量或字符串之外(其他所有转义序列都不可以)!如下:

❯ cat CharTest.java
public class CharTest {
  public static void main(String\u005B\u005D args) { // 转义序列 \u 可以出现在加引号的字符字面量或字符串之外
    System.out.println("Hello!\nWorld!"); // 所有转义序列都可以出现在加引号的字符字面量或字符串中
  }
}
❯ java CharTest.java // 在 JDK 11 中,单个 Java 源文件不再需要 javac 命令
Hello!
World!

Note!Unicode 转义序列会在解析代码之前得到处理。
例如:"\u0022 + \u0022" 并不是一个由一对双引号(")括起来的字符串:\u0022 + \u0022 ,而是会解析成 "" + "" 形成的一个空串。如下:

❯ cat CharTest.java
public class CharTest {
  public static void main(String\u005B\u005D args) {
    System.out.println("->" + "\u0022 + \u0022" + "<-"); // Unicode 转义序列会在解析代码之前得到处理

    System.out.println("Hello\u0022 + \u0022World!");
  }
}
❯ java CharTest.java
-><-
HelloWorld!

Note!需要当心注释中的 \u
如果注释中出现 \u000A 则会产生语法错误,因为 \u000A 会被提前解析为换行符 \n
同时如果在注释中 \u 后面没有跟4个十六进制数,也会产生语法错误。如下:

❯ cat CharTest.java
public class CharTest {
  public static void main(String\u005B\u005D args) {
    System.out.println("Hello World!"); // 这是一个 \u000A 的测试
  }
}
❯ java CharTest.java
CharTest.java:3: 错误: 不是语句
    System.out.println("Hello World!"); // 这是一个 \u000A 的测试
                                                       ^
CharTest.java:3: 错误: 需要';'
    System.out.println("Hello World!"); // 这是一个 \u000A 的测试
                                                          ^
2 个错误
错误: 编译失败

❯ cat CharTest.java
public class CharTest {
  public static void main(String\u005B\u005D args) {
    System.out.println("Hello World!"); // 这是一个 \u 的测试
  }
}
❯ java CharTest.java
CharTest.java:3: 错误: 非法的 Unicode 转义
    System.out.println("Hello World!"); // 这是一个 \u 的测试
                                                  ^
1 个错误
错误: 编译失败

数据类型转换

基本数据类型相互转换

基本数据类型转换原则
低 ---------------------------------------------- 高
byte, short, char -> int -> long -> float -> double       浮点数优先级 > 整数优先级
  • 低级数据高级数据 ==> 自动转换
  • 高级数据低技数据 ==> 强制转换(通过在变量前加 (目的类型) 实现)
public class TypeCast {
    public static void main(String[] args) {
        System.out.println("低 -> 高");
        byte num1 = 120;
        int num2 = num1;
        System.out.println(num1);
        System.out.println(num2);

        System.out.println("高 -> 低");
        long num3 = 233L;
        int num4 = (int) num3; // 强制转换
        System.out.println(num3);
        System.out.println(num4);

        System.out.println("低 -> 高 & 整数 -> 浮点数");
        long num5 = 12345678L;
        float num6 = num5;
        System.out.println(num5);
        System.out.println(num6);

        System.out.println("高 -> 低 & 浮点数 -> 整数");
        float num7 = 1234.567F;
        long num8 = (long) num7; // 强制转换
        System.out.println(num7);
        System.out.println(num8);
    }
}
/* 输出如下:
低 -> 高
120
120
高 -> 低
233
233
低 -> 高 & 整数 -> 浮点数
12345678
1.2345678E7
高 -> 低 & 浮点数 -> 整数
1234.567
1234
 */
不能对 boolean 类型数据进行类型转换

can not cst boolean

类型转换时可能会存在内存溢出或精度丢失等问题
public class TypeCast {
    public static void main(String[] args) {
        System.out.println("高 -> 低 & 内存溢出");
        int num9 = 128;
        System.out.println(num9);
        System.out.println((byte) num9);

        System.out.println("高 -> 低 & 精度问题");
        System.out.println((int) 23.45);
        System.out.println((int) -23.4556F);
    }
}

/* 输出如下:
 高 -> 低 & 内存溢出
 128
 -128
 高 -> 低 & 精度问题
 23
 -23
 */
char 类型和 int 类型的互相赋值
  • 0 ~ 65535 范围内,charint 类型可以互相赋值
  • 若显式定义 int 变量后,转换为 char强制转换
public class Char2Int {
	public static void main(String[] args) {
		char a1 = 'a';
		int a2 = 'a';
		System.out.println(a1);
		System.out.println(a2);
		
		int A1 = 65;
		char A2 = 65;
		System.out.println(A1);
		System.out.println(A2);
		
		char B1 = 'B';
		int B2 = B1;
		System.out.println(B1);
		System.out.println(B2);
		
		int b1 = 98;
		char b2 = (char) b1;
		System.out.println(b1);
		System.out.println(b2);
	}
}

/* 输出如下:
 a
 97
 65
 A
 B
 66
 98
 b
 */
运算符对基本数据类型转换的影响
  • 当用一个二元运算符连接两个值时(例如 n + f,n 是整数,f 是浮点数),要先将两个操作数转换为同一种类型,然后再进行计算。
    —— Java 核心技术(卷 I) 3.5.3 节

    jshell> int n = 5;
    n ==> 5
    
    jshell> float f = 1.0F;
    f ==> 1.0
    
    jshell> int result = n + f;
    |  错误:
    |  不兼容的类型:float转换到int可能会有损失
    |  int result = n + f;
    |               ^---^
    
  • 赋值运算符(=+=-=等)会自动将计算结果进行强制类型转换。

    jshell> int n = 1;
    n ==> 1
    
    jshell> float a = 0.5F;
    a ==> 0.5
    
    jshell> float b = 0.8F;
    b ==> 0.8
    
    jshell> n += a + b;
    $11 ==> 2 // 相当于 n += (int)(a + b)
    
    jshell> n
    n ==> 2
    

基本数据类型与包装类之间的自动转换

jshell> Integer a = 2; // 自动装箱
a ==> 2

jshell> int b = Integer.valueOf(3); // 自动拆箱
b ==> 3

String 与其他类型数据之间的转换

jshell> "My age is " + 14
$16 ==> "My age is 14"

jshell> 14 + " is my age"
$17 ==> "14 is my age"

jshell> 7 + 5 + " is my age"
$18 ==> "12 is my age"

jshell> 7 + 5 + " is my age, my age is " + 12
$19 ==> "12 is my age, my age is 12"

当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串。

变量

变量三要素

  • 变量类型
  • 变量名
  • 变量值

变量声明(并赋值)

变量类型 变量名 = 变量值;
  • Java 中可以一行声明多个变量(但不推荐一行声明多个变量)
    int a = 1, b = 2, c = 3;
    
    a ==> 1
    b ==> 2
    c ==> 3
    
    int a, b, c;
    
    a ==> 0
    b ==> 0
    c ==> 0
    

Note!Java 是大小写敏感的。

public class CaseSensitive {
    public static void main(String[] args) {
        System.out.println("Java 是大小写敏感的:");
        String man = "Jack";
        String Man = "John";
        System.out.println("man: " + man);
        System.out.println("Man: " + Man);

        System.out.println("==================");
        String woman = "Rose";
        // String woman = "Mei";
        System.out.println("woman: " + woman);
    }
}

/* 输出如下:
 Java 是大小写敏感的:
 man: Jack
 Man: John
 ==================
 woman: Rose
 */

case sensitive

按照作用域划分,Java 中有 3 种变量

  • 类变量: 独立于方法之外的变量,用 static 修饰,再用 final 修饰的话就是常量 (修饰符间没有顺序,谁前谁后都可以)。
  • 实例变量: 可以不初始化,实例创建时,会自动将实例变量初始化为所属类型的默认值(数字 ⇒ 0, boolean ⇒ false引用类型 ⇒ null)。
  • 局部变量: 使用前必须声明和初始化值
public class Variable{
    static final String ZHANG_SAN = "zhangsan"; // final、static 为修饰符,不存在先后顺序
    static int allClicks = 0; // 类变量

    String str = "Hello, World"; // 实例变量

    public static void main(String[] args) {
        int num = 0; // 局部变量
        System.out.println(num);
        System.out.println(ZHANG_SAN);
    }
}

运算符

自动升型

在运算中,运算结果类型会自动升为混合运算中类型最高的类型

jshell> Integer.MAX_VALUE
$1 ==> 2147483647

jshell> Integer.MAX_VALUE + 1
$2 ==> -2147483648

jshell> Integer.MAX_VALUE + 1L
$3 ==> 2147483648

jshell> 1 + 1.0
$4 ==> 2.0

instanceof

instanceof 用于判断一个对象是否属于指定的类型

class Human {}
class Man extends Human {}

public class InstanceOf {
    public static void main(String[] args) {
        Human human = new Human();
        Man man = new Man();
        System.out.println(man instanceof Man);
        System.out.println(man instanceof Human);
        System.out.println(man instanceof Object);
        System.out.println(human instanceof Object);
    }
}

逻辑运算符 | 短路运算

短路运算:

false && [Any...] // 后面没有执行
true || [Any...] // 后面没有执行
public class ShortOutOperation {
    public static void main(String[] args) {
        int c = 5;
        boolean n = (c < 4) && (c++ > 5); // c < 4 为 false, 如果执行了后面,c 必然变成 6
        System.out.println(n);
        System.out.println(c);

        int d = 5;
        boolean m = (d > 4) || (d-- == 4); // d > 4 为 true, 如果执行了后面,d 必然变成 4
        System.out.println(m);
        System.out.println(d);
    }
}

/* 输出如下:
 false
 5
 true
 5
 */

位运算

  • &: 与
  • |: 或
  • ~: 非
  • ^: 异或
    • ⇒ 相同为0,不同为1
    • ⇒ 可以理解为 : 相异为1(true),不相异为0(false)
    • 二进制加法: 0+0=0,0+1=1
  • <<: 左移 ⇒ *22 << 2 ⇒ 23 = 8
  • >>: 右移 ⇒ /28 >> 23√8 = 2

字符串连接 +

只要 + 两边任一边有字符串,就会进行连接。

jshell> "" + 10 + 20
$1 ==> "1020"

jshell> 10 + "" + 20
$2 ==> "1020"

jshell> 10 + 20 + ""
$3 ==> "30"

运算符优先级

不要刻意记忆,不确定的用括号 () 包起来

参考资料

  1. 关于Java代码中注释的使用
  2. 生成javadoc时 @thorws 和 @exception 的区别
  3. Java-文档注释
  4. On Java 8 : 基本类型的存储
  5. Java Core I : 3.3 数据类型
  6. Java 基本数据类型
  7. 结合Java详谈字符编码和字符集
  8. Java为什么选择unicode字符集?字符编码的那些事
  9. 浅谈Unicode和char的关系(Java)
  10. Unicode 及编码方式概述
  11. 彻底弄懂 Unicode 编码
  12. unicode、utf-8、utf-16的理解 和 java的char类型所使用的编码
  13. java 语言使用的字符码集是 Unicode
  14. Java中的转义字符
  15. Java基础常见转义字符(完整归纳)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十甫寸木南

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值