标识符
◼ Java标识符:以字母、下划线()或美元符号($)开头,随后跟随字母、下划线()、美元符号($) 或数字。
◼ 标识符是大小写敏感的:
◼ 有效的:identifier、userName、User_name、sys_varl、$change、_3 、OK。
◼ 非法的:#name,25name,&time
◼ 标识符不能是关键字和保留字,如:if、class、goto等
Java关键字 // 注:51个关键字,2个保留字,都是小写
Java关键字(续)
新的关键字:var
◼ Java10 引入 var 用于声明局部变量:
var x=100;
var s=”abc”;
for(var i=0; i<10; i++)
注意:
◼ var变量必须在定义时初始化: var x; x=100; ×
◼ var变量初始化后就确定数据类型,之后不能修改:var s=”abc”; s=100; ×
◼ 类成员变量、方法的参数、返回类型也不能使用var
Java运算符
注意:Java没有sizeof运算,也没有&取地址运算
数据类型
注:Java没有unsigned关键字
包装类概念
◼ Java语言不把基本数据类型的变量视为对象
◼ 为了满足万物皆对象的理念,需要对基本数据类型的变量进行封装处理变成对象,而负责这项任务的相 关类,称为包装类 (wrapper class)
基本类型和包装类区别
◼ 定义不同:包装类是对象,基本数据类型不是
◼ 使用方式不同:基本数据类型可以直接赋值,包装类一般需要用 new 来分配存储空间,在泛型集合中必须使用包装类,不能使用基本数据类型,如:List<Integer>
◼ 初始值不同:基本类型的初始值如 int 为 0,boolean 为 false,而包装类型的初始值为 null
◼ 存储方式和位置不用:基本数据类型存储在栈中(stack),包装类型是将对象放在堆中(heap),然后通过引用来使用(引用放在 stack 中)
包装类特点
◼ 基本类型不能赋值为 null,如:int x = null; ×
◼ 但包装类型可以,如:Integer x = null; √
◼ 包装类有自己的属性(公有静态常量)和方法,而基本数据类型则没有:
◼ Integer.MAX_VALUE:返回int最大值(2147483647)
◼ Integer.SIZE:返回int类型位数(32,1字节=8位) 注:Boolean类没有SIZE属性
◼ Integer.parseInt(“数字串”) :将数字串转为int值
◼ Integer.toString(int):将int转为字符串
补充:包装类常用常量(属性)和方法 – 以Integer类为例
装箱和拆箱
1 | int a; //基本类型 |
拆箱操作:包装类对象→值类
装箱操作:值类型→包装类对象
注:装箱、拆箱会损耗性能
关于:无符号整型处理
注:Java 没有 unsigned 关键字,但有相应的 unsigned 函数
◼ 例如:byte是有符号整型,范围是:-128~+127
◼ 如果想把byte看作无符号整型,它的范围应该就是:0~255
◼ 如何把一个byte按无符号整数转换为int?
↓
1 | byte a = -1; |
将负数的补码全部看成有效数字
关于:大数据 BigInteger 和 BigDecimal
◼ BigInteger:任意大小的整数(内部使用一个int数组来存储大整数)
◼ BigDecimal:任意大小且精度完全准确的浮点数
import java.math.BigInteger;
1 | BigInteger a = new BigInteger("12345678901234567890"); // 注:大数据要用字符串处理的 |
◼ BigInteger 的转换:
1 | Long x = 1234567890L; |
基本类型用法
变量和常量
(1)方法中的变量必须经初始化后才能被使用:
1 | ... |
(2)类成员变量初始化:
◼ Java允许在类定义时直接初始化成员变量
◼ 但一般都是通过构造函数进行成员变量初始化
◼ 如果以上都没有,则在对象创建时被自动初始化:
◼ 数值型成员:默认值为 0,如 int 为 0,double 为 0.0
◼ boolean 成员:默认值为 false 值
◼ char 成员:默认值为’\u0000’ (其实也是 0,空字符)
◼ 所有对象变量(如 String):默认值为 null
类成员变量初始化示例
1 | public class Main { |
运行结果
常量(符号常量)
使用final来定义符号常量(一般用大写字符):
◼ 定义符号常量:final double PI = 3.14159; // 变量声明前面加 final 变常量
◼ 常量可先声明后赋值:final double PI; PI = 3.141519; √
◼ 常量赋值后就不可再修改:PI = 3.14; × // final常量不可修改
◼ 系统提供的符号常量:一般是公有的静态常量
public static final
,可以直接通过类名调用 如:Integer.MIN_VALUE、Double.MAX_VALUE、Character.SIZE
数据输出格式的控制
◼ 方法1:String.format(“格式串”, 数据) // 推荐使用
◼ 方法2:System.out.printf(“格式串”, 数据)
1 | int a = 100; |
整数/浮点型
◼ 整数类型:byte、short、int、long
如:17 (十),0b10 (二),017 (八),0xff00 (十六),17L (长整型)
◼ 浮点数:float、dobule
如:3.14、3.14f、3.02e23、123.4D (类型字符大小写均可)
注意:
float a = 3.4f; √ ‘f’ 不能省略
float a = 3.4; ×
double a = 3.4; √说明:Java中普通的浮点数默认是 double 类型
同样的
long a = 123;// 编译通过,因为123是int,所以被long类型的值接收没问题
long b = 123L; // 编译通过,建议这样写。
long c = 123455678123455;// 编译不通过,因为123455678123455已经超出了int的范围,这个已经不是int了,所以编译不通过
long d = 123455678123455L;// 编译通过所以说无论如何建议float类型加F,long类型加L。
算术运算注意
◼ 自增与自减运算符只适用于变量,如:10++; ×
◼ 两个整数类型的数据做除法时,结果只保留整数部分:3/2 = 1 , -9/2 = -4
◼ % 取余运算不仅能用于整型,也能用于浮点类型:
9%2 = 1 9.5%2 = 1.5 (余数可为浮点数) -9%2 = -1 (余数可为负数)
算术运算注意
◼ 整数除0时会报错
◼ 浮点数除0时,不会报错,会返回几个特殊值:
1 | int i = 1/0; // 报错 |
浮点数相等的判断
◼ 浮点数在计算机中常常无法精确表示,并且计算可能出现误差,因此,判断浮点数相等不要用==判断
◼ 正确方法:利用差值绝对值小于某个临界值来判断
1 | double x = 1.0 / 10; // x = 0.1 |
整数运算溢出问题
◼ 整数由于存在范围限制,如果计算超出了范围,就会产生溢出
◼ 溢出不是报错,只是结果不符合预期
1 | short x = 32767; |
整数移位运算
注:对 byte 和 short 会首先转换为 int 再进行位移
◼ >>:右移,正数高位补 0,负数高位补 1(带符号右移)
◼ <<:左移,并且在低位补 0
◼ >>>:无符号右移,无论正负高位都补
1 | int n=7; // n=7 00000000 00000000 00000000 00000111 |
一般情况:左移 <<n 位:相当于整除 2ⁿ,右移 >>n 位:相当于整除 2ⁿ
整数位运算
◼ 位运算是按位进行与、或、非和异或的运算
◼ 两个整数位运算:按位对齐,然后依次对每位进行位运
1 | int n=7; // n=7 00000000 00000000 00000000 00000111 |
类型自动提升和强转
◼ 参与运算的两个数类型不一致,那么计算结果以较大类型为准
◼ 浮点数强转为整数时小数部分丢弃
◼ 尽量避免将大范围的整数转型为小范围的整数,以免数据丢失或错误
1 | short s = 1234; |
boolean类型
◼ boolean有两个值:true 和 false(小写)
◼ 特别注意:数字值不能自动转换为boolea
1 | int x = 1; |
短路运算:如果一个布尔运算表达式能提前确定结果,则后续的计算不再执行,直接返回结果
例如:false&&x,true||x :x被短路不参与运算
char类型
◼ 一个 char 代表一个 16bit 无符号的 Unicode 字符
Unicode 称为统一码或万国码,它为每种语言的每个字符设定了唯一二进制编码 以满足跨语言、跨平台的文本处理要求,utf-8、utf-16 都是Unicode 规范的实现
◼ 一般用法:
◼ 正确:char ch1=’a’, ch2=’\n’ , ch3=’中’; // 注:汉字也是一个 Unicode 字符
◼ 错误:char ch1=’abc’, ch2=”a”; // 注:char 类型使用单引号,且仅有一个字符
◼ 标准写法:
char ch='\u0041';
等价于 ch = ‘A’;
以 \u 开头 + 4 个 16 进制数字 注:char 类型使用单引号,且仅有一个字符 注:必须是 4 位,’\u41’ ×
常用的转义符
char 和 int 之间的转换
◼ char和int可以转换:
1 | char ch1 = 65; |
字符的检测方法
返回值为 true 或 false
◼ Character.isLetter(char) – 指定字符是否是字母
◼ Character.isDigit(char) – 指定字符是否是数字
◼ Character.isLetterOrDigit(char) – 指定字符是否是字母或数字
◼ Character.isWhitespace(char) – 指定字符是否是空格
◼ Character.isLowerCase(char) – 指定字符是否是小写字母
◼ Character.isUpperCase(char) – 指定字符是否是大写字母
◼ Character.toUpperCase(char):字母小写变大写
◼ Character.toLowerCase(char):字母大写变小写
Character:char类型的包装类
字符串用法
◼ String不是基本类型,而是一个class类
◼ 用双引号 “…” 表示字符串
◼ 与C和C++不同,String不用 ‘\0’ 作为结束
创建方法:
方法1:String s1 = “hello”; // 注:”Hello”是一个字符串常量
方法2:String s1 = new String(“hello”); // 使用构造函数创建
String s2 = “”; // 空串,长度为0的串
String s3 = null; // 空对象(没有分配内存空间)
注意:String两种创建方法的差异
1 | String s1 = "Hello"; |
字符串的常用操作
- 字符比较
- 字符串长度和字符获取
- 字符串连接
- 字符串分割
- 字符串查找
- 获取子串
- 字符串判断
- 字符串匹配
- 字符串替换
- 字符串去空白
- 字符串转换
- String、StringBuffer、StringBuilder
字符串比较
忽略大小写的比较:equalsIgnoreCase()
◼ equals()
:比较字符串的内容是否相同
◼ ==:比较的是不是同一个引用(地址)
1 | String s1 = "abc"; |
强调:字符串内容比较是否相同时要用 equals() 方法,不要用 ==
1 | String s3 = new String("abc"); |
◼ compareTo(String s)
:字典比较
◼ 如果原串小于 s 串则返回负值,如果原串大于 s 串则返回正值,如果原串等于 s 串则返回零
◼ 如果比较字符串有包含关系,返回的值是它们长度的差值
◼ 一般比较过程:先比较第一个元素,如果相等再比较第二个元素…,返回元素之间的差值
1 | String s1 = "abc"; |
字符串长度和字符获取
◼ length()
:获取串的长度(字符个数)
◼ charAt(int index)
:获取指定索引位置处的字符(char) // index索引值从0开始
1 | String s="student"; |
1 | String s="time over"; |
字符串连接
1 | String s1 = "Hello"; |
程序阅读:
1 | nt a = 1, b=2; |
◼ 思考题:将下面 int 值视为字符,如何将它们连接拼成一个字符串,结果又是多少?
int a = 65; int b = 97; int c = 48;
◼ 答案:String s = “” + (char)a + (char)b + (char)c; 结果 s = “Aa0”
字符串分割
注:分割不会改变原字符串的内容,而是返回了一个新字符串
◼ split(String s)
:根据给定s拆分字符串(返回字符串数组)
1 | String s1="12:25:30"; |
注:点号比较特殊,要用”\.”表示
字符串查找
◼ indexOf(String s)
:获取指定字符串第一次出现的索引值
◼ indexOf(String s, int fromIndex)
:从指定索引位置开始,获取指定字符串第一次出现的索引值
◼ lastIndexOf(String s)
:获取指定字符串最后一次出现的索引值
1 | String s="I am a student"; |
获取子串
◼ substring(int start)
:从指定位置开始一直截取到末尾
◼ substring(int start, int end)
:截取 [start,end-1] 范围子串
1 | String s1="time is over"; |
字符串判断
◼ contains(String s)
:是否包含指定字符串
◼ startsWith(String s)
:是否以指定的字符串开头
◼ endsWith(String s)
:是否以指定的字符串结尾
◼ isEmpty()
:判断是否为空串
String s=”I am a student”;
s.contains(“stu”) // true
s.startsWith(“ent”) // false
s.endsWith(“ent”) // true
s.isEmpty() // false
“”.isEmpty(); // true,””是长度为0的空串(注:不是null)
“ “.isEmpty(); // false,” “是长度不为0的空白串
字符串匹配
◼ matches(String reg):检查字符串是否与给定的正则式匹配
正则式:是一种”规则字符串”,用于匹配字符串中字符组合的模式
String reg = “^[0-9]+$”; // 定义一个正则式(字符串)
“789”.matches(regex) // true
“00123”.matches(regex) // true
“123a”.matches(regex) // false
“98 41”.matches(regex) // false
正则式 “^[0-9]+$” 含义:
◼ ^ 表示开头,$ 表示结束
◼ [0-9] 表示:匹配所有数字字符 (0~9)
◼ + 表示:1 次或多次
◼ “^[0-9]+$”表示:匹配数字,1个或多个,即数字串(包括0开头的)
字符串替换
注:替换不会改变原字符串的内容,而是返回了一个新字符串
◼ replace(String oldS, String newS)
:用新串 newS 替换老串 oldS
1 | String s1 = "time over"; |
字符串去空白
注:不会改变原字符串的内容,而是返回了一个新字符串
◼ trim()
:去掉前后空白字符,包括:空格,\t,\r,\n
1 | String s1 = " \tHello\r\n "; |
字符串转换
注:转换也不会改变原字符串的内容,而是返回了一个新字符串
◼ getBytes()
:将字符串转成字节数组 (byte[ ],默认Unicode编码值)
◼ toLowerCase()
:大写字母变成小写
◼ toUpperCase()
:小写字母变成大写
String s=”Hello”; byte[]
s1 = s.getBytes(); // [72, 101, 108, 108, 111] ‘H’→72 …
String s2 = s.toUpperCase(); // “HELLO”
String s3 = s.toLowerCase(); // “hello”
注:s 串本身都没有改变
◼ toCharArray()
:将字符串转成字符数组
◼ valueOf(Object obj)
:将任意类型转成字符串
转换汇总:
◼ 字符串 → 数值:以 int/Integer 为例,其他类型类似
(1)String转换为int:
int i = Integer.parseInt(“123”); // i=123,默认为十进制
int n = Integer.parseInt(“ff”, 16); // n=255,按十六进制转换
(2)String转换为Integer:
Integer x = Integer.valueOf(“123”); // 串转换为Integer对象
注意:转换时对数据格式要求严格
int i = Integer.parseInt(“123.4”); ×
double d = Double.parseDouble(“1.23a”); ×
// 均会报错:NumberFormatException
◼ 数值 → 字符串:
方法1:使用String.valueOf()方法
String s = String.valueOf(123); // value可为任意类型,包括Object
方法2:使用toString()方法
String s = Integer.toString(123); // 其他类型类似
方法3:使用”+”连接 (最直接)
String s = “” + value; // value为任意数值类型
转换汇总:
◼ 字符数组 → 字符串
使用 String 构造函数转换
1 | char[ ] charArr = { 'a', 'b', 'c' }; // 字符数组 |
◼ 字符串 → 字符数组
使用 toCharArray()
方法转换
1 | String str = "abc"; |
补充:
Arrays.toString(一维数组)
:可以将任意类型一维数组变成字符串 例如:System.out.print( Arrays.toString(charArr) );
//输出结果 [a, b, c]
关于 String、StringBuffer、StringBuilder
◼ String 字符串是不可改变的,也就是说一旦创建了 String 对象,那它的值就无法改变!
◼ 要对字符串自身进行修改,可使用 StringBuffer 类
◼ StringBuffer 对象能被多次修改,且不产生新的对象!
◼ StringBuilder 和 StringBuffer 本质上没区别,只是 StringBuilder 去掉了线程安全,不同步,效率更高。
StringBuffer常用方法
这些操作都将修改 StringBuffer 对象自身
方法 | 功能 |
---|---|
append(String s) | 将s追加到尾部 |
reverse() | 字符串内容反转 |
int capacity(): | 获取容量(不是length值) |
setCharAt(int index, char ch): | 在指定位置替换一个字符 |
deleteCharAt(int index): | 在指定位置删除一个字符 |
delete(int start, int end): | 删除start到end-1位置的子串 |
insert(int offset, int i): | 将整数 i 的字符串形式插入到offset位置 |
replace(int start, int end, String str): | 将start至end-1位置内容替换为str |
StringBuffer用法示例
1 | StringBuffer sb = new StringBuffer("Hello"); // StringBuffer sb = "Hello"; × |
String与StringBuilder的相互转换
◼ String → StringBuilder:
1 | String s = "hello"; |
◼ StringBuilder → String:
1 | StringBuilder sb = new StringBuilder(); |
StringBuffer用法示例
逆序整数n,不使用分解
1 | public int reverse(int n) { |
StringBuffer串的比较
◼ StringBuffer 串的比较,不能直接使用
equals()
◼ 应该先使用
toString()
方法将 StringBuffer 对象转换为 String 字符串,再使用equals()
方法比较:sb1.toString().equals( sb2.toString() )
因为 StringBuffer 的
equals()
方法继承 Object,你使用的equals()
方法是 Object 的。其比较的是两个对象,对于任何非空引用值 str1 和 str2,当且仅当 str1 和 str2 引用同一个对象时,此方法才返回 true
StringBuffer用法示例
判断s是否是回文串
1 | public boolean isPalindrome(String s) { |
控制语句
switch语句
1 | switch (expression){ // 可以是 int、byte, short、char 或 String、枚举 类型,不允许使用浮点或long表达式 |
switch示例1:
1 | public class Main { |
switch示例2:
1 | public class Main { |
while/do…while/for
break、continue
◼ 特殊用法:break、continue后接标签名
◼ 什么是标签:
◼ 标签可标识控制需要转换到的任何有效语句(块)
◼ 标签用法:
标签: 语句(块) 即在有效语句块前加个”标签名:”
标签示例1
1 | public class Main { |
运行结果:
Pass 0: 0 1 2 3 4
标签示例 2
1 | public class Main { |
编程练习
- 字符统计:统计字符串中大写字母、小写字母、数字、空格以及其他字符个数
- 回文判断:如”abba”、 “abcba”是回文,”abcd”不是回文
- 随机整数:生成一个区间在 [MIN, MAX] 的随机整数
- 素数:输出1-100之间的所有素数,并统计个数
- 水仙花数:一个三位数,其各位数字立方和等于该数
- 计算圆周率π:
- 递归:求 2+4+6+…+100之和
- 最小值和最大值:使用Math类
字符串统计
Ex_1.java
1 | public class Ex_1 { |
回文判断
Ex_2.java
1 | public class Ex_2 { |
随机整数:区间在 [min, max]
Ex_3.java
1 | public class Ex_3 { |
Random.nextInt():产生随机整数
Random.nextInt(t):产生 [0,t) 随机整数
素数
Ex_4.java
1 | public class Ex_4 { |
水仙花数
例如:153 = 1^3 + 5^3 + 3^3 就是一个水仙花数
Ex_5.java
1 | public class Ex_5 { |
计算圆周率π
Ex_6.java
1 | public class Ex_6 { |
递归:求 2+4+6+…+100
分析:S = 100 + 98 + 96 + … + 2
把每个值看成是一个函数返回的值
S(100) = 100 + S(98) = 100 + 98 + S(96)
= 100 + 98 + 96 + S(94) …
= 100 + 98 + 96 + 94 + … + S(2)
= 100 + 98 + 96 + 94 + … + 2 得到递归公式:
递归程序
1 | public class Ex_7 |
最小值和最大值
Ex_6.java
1 | public class Ex_8 { |
Math类常用属性和方法
属性或方法 | 说明 |
---|---|
PI | π值 |
E | e值 |
abs() | 求绝对值 |
sqrt() | 求平方根 |
pow(double a, double n) | a的n次幂 |
exp(double n) | e的n次幂 |
min(double d1, double d2) | 返回d1与d2中的小者 |
max(double d1, double d2) | 返回d1与d2中的大者 |
ceil(double a) | 返回大于或等于 a 的最小整数 |
floor(double a) | 返回小于或等于 a 的最大整数 |
round(double d) | 四舍五入取整(将原来的数字加上 0.5 后再向下取整) |
random() | 返回 [ 0,1) 的随机数 |