SpringBoot课——Java语法(上)
SpringBoot课——Java语法(上)
变量、运算符、输入与输出
类似于C#,Java的所有变量和函数都要定义在class中。
内置数据类型
在Java语言中,属于引用类型的是:
类类型
接口
字符串
数组
类型
字节数
举例
byte
1
123
short
2
12345
int
4
123456789
long
8
1234567891011L
float
4
1.2F
double
8
1.2, 1.2D
boolean
1
true, false
char
2
'A'
一、字符串处理相关类
二、栈操作
三、日期与时间类
部分知识
String类表示的字符串是常量,一旦创建后,内容和长度都无法改变。
而StringBuffer表示字符容器,其内容和长度都可以随时改修改。
在操作字符串时,如果该字符串仅用于表示数据类型,使用String类即可,
但是如果需要对字符串中的字符进行增删操作,则使用StringBuffer类。
String类覆盖了Object类的equals()方法,而StringBuffer类没有覆盖Object类的equals()方法。
public class Example { public static void main(String[] args) { String str1 = new String("a"); String str2 = new String("a"); System.out.println(str1.equals(str2)); //打印 true StringBuffer sb1 = new StringBuffer("a"); StringBuffer sb2 = new StringBuffer("b"); System.out.println(sb1.equals(sb2)); //打印 false } }String类对象可以用操作符+进行连接,而StringBuffer类对象之间不能
简单点说,Java 中的传递,是值传递,而这个值,实际上是对象的引用。
传递的值在栈中,直接拷贝一份值传递,改变的形参不会对实参造成影响
传递的值在栈中存放的是地址(引用),先根据栈中的地址找到在堆上的值,然后把地址拷贝一份(拷贝的地址是一个值),此时形参和实参指向堆上同一个地址,形参的修改导致了实参的改变。
Java异常处理
(1)存在异常(数组下棋越界)但没有处理的源代码:
int i = 0; String course[] = { "Java", "Java EE", "Android" }; while (i < 4) { System.out.println(course[i]); i++; } System.out.println("处理完毕");运行效果:
(2)通过定义方法处理异常的源代码(程序的可读性差):
static int checkScore(int s) { //类的静态方法 if (s < 0 || s > 100) return -1; else return 1; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int s; do{ System.out.println("请输入一个有效成绩:"); s=scanner.nextInt(); if(checkScore(s)==-1){ System.out.println("成绩输入无效,应在0-100范围内!"); }else { System.out.println("成绩输入有效!"); scanner.close(); break; } }while(true); }(3)通过try...catch...语句处理异常的源代码(程序的可读性好):
int i = 0; String course[] = { "Java", "Java EE", "Android" }; while (i < 4) { try { System.out.println(course[i]); //捕捉异常 } catch (ArrayIndexOutOfBoundsException e) { // 数组下标越界异常 System.out.println("数组下标越界啰!"); // e.printStackTrace(); //输出异常信息 } i++; } System.out.println("处理完毕");
try...catch是基本结构,还可以选配finally子句
方法printStackTrace()由类Throwable提供,用于输出系统捕捉到的异常信息
与使用方法处理异常相比,使用异常处理语句(类)的程序的可读性更好
异常处理在后面学习多线程、Java I/O操作(文件读写)、Java网络编程和JDBC编程时会大量使用
运行效果:
注意
Java中如果是
字符串的话,不能使用==来判断是否相等因为Java中==判断是会判断两个地址是否相等
如果想要判断两个字符串是否相等,需要使用String的方法
equalsString a ="a"; String b ="a"; if(a.equals(b)){ System.out.println("a"); }通常反过来写
if("M".equals(op){ System.out.println(op); })
常量
使用
final修饰final int N = 110;示例:
类型转化——与C++相同
显式转化:
int x = (int)'A'
显式转化可以从高转到低——(强制转换)——丢失超出低精度的数据
隐式转化:
double x =12,y = 4*3.3;或int y = 12; double z = y;
隐式转换只能从低到高变,从高到低变会报错————高是精度的意思
IDEA 中写输出一种简写方式
sout加补全=System.out,println
表达式
与C++、Python3类似:
int a=1,b=2,c=3; int x =(a+b)*c; x ++;输入
方式1,效率较低,输入规模较小时使用。
Scanner sc = new Scanner(System.in); String str = sc.next(); // 读入下一个字符串 int x = sc.nextInt(); // 读入下一个整数 float y = sc.nextFloat(); // 读入下一个单精度浮点数 double z = sc.nextDouble(); // 读入下一个双精度浮点数 String line = sc.nextLine(); // 读入下一行
Scanner中可使用方法为:
其中
next()方法 读入的没有空格,nextLine()读入的有空格Scanner sc = new Scanner(System.in); String str = sc.next(); System,out,println(str); //输入Hello World //只输出了Hello方式2,效率较高,输入规模较大时使用。注意需要抛异常。
package com.yxc; import java.io.BufferedReader; import java.io.InputStreamReader; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = br.readLine(); System.out.println(str); } }输出
方式1,效率较低,输出规模较小时使用。
System.out.println(123); // 输出整数 + 换行 System.out.println("Hello World"); // 输出字符串 + 换行 System.out.print(123); // 输出整数 System.out.print("yxc\n"); // 输出字符串 System.out.printf("%04d %.2f\n", 4, 123.456D); // 格式化输出,float与double都用%f输出
println和printf可以输出任意类型的东西
println会在输出末尾自动回车换行 而
方式2,效率较高,输出规模较大时使用。注意需要抛异常。
import java.io.BufferedWriter; import java.io.OutputStreamWriter; public class Main { public static void main(String[] args) throws Exception { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); bw.write("Hello World\n"); bw.flush(); // 需要手动刷新缓冲区 } }
判断语句
与C++、Python中类似(一模一样)
if-else语句
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int year = sc.nextInt(); if (year % 100 == 0) { if (year % 400 == 0) System.out.printf("%d是闰年\n", year); else System.out.printf("%d不是闰年\n", year); } else { if (year % 4 == 0) System.out.printf("%d是闰年\n", year); else System.out.printf("%d不是闰年\n", year); } } }switch语句
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int day = sc.nextInt(); String name; switch (day) { case 1: name = "Monday"; break; case 2: name = "Tuesday"; break; case 3: name = "Wednesday"; break; case 4: name = "Thursday"; break; case 5: name = "Friday"; break; case 6: name = "Saturday"; break; case 7: name = "Sunday"; break; default: name = "not valid"; } System.out.println(name); } }逻辑运算符与条件表达式
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int year = sc.nextInt(); if (year % 100 != 0 && year % 4 == 0 || year % 400 == 0) System.out.printf("%d是闰年\n", year); else System.out.printf("%d不是闰年\n", year); } }
循环语句
while循环
与C++、Python类似,例如:
int i=0; while(i < 5) { System.out.println(i); i ++ ; }do while循环
与C++、Python类似,例如:
//do while循环 int j = 0; do { System.out.println(j); j ++; } while(j <5);do while语句与while语句非常相似。唯一的区别是,do while语句限制性循环体后检查条件。不管条件的值如何,我们都要至少执行一次循环。
示例:
//while循环 int i=0; while (i < 0){ System.out.println("while"); i ++; } //do while循环 int j = 0; do { System.out.println("do while"); j ++; } while(j <0);执行结果:
do while与while只有在判断条件不成立时才不一样for循环
与C++、Python类似,例如:
for (int i = 0; i < 5; i ++ ) { // 普通循环 System.out.println(i); } int[] a = {0, 1, 2, 3, 4}; for (int x: a) { // forEach循环 System.out.println(x); }IDEA快捷命令
使用
fori
使用
foreach
数组
Java中的数组与C++中的数组类似。
数组初始化
初始化定长数组,长度可以是变量,可以在初始化时赋值。
int[] a = new int[5]; // 初始化长度为5的int数组,初始值为0 int n = 10; float[] b = new float[n]; // 初始化长度为n的float数组,初始值为0.0F char[] c = {'a', 'b', 'c'}; // 初始化长度为3的char数组,初始值为:'a', 'b', 'c' char[] d = c; // d与c地址相同,更改c中的元素,d中的元素也会改变数组元素的读取与写入
与C++类似。
int[] a = new int[5]; for (int i = 0; i < 5; i++) { a[i] = i; } for (int i = 0; i < 5; i ++ ) { System.out.println(a[i] * a[i]); }数字转字符串输出
//数组变字符串输出 char[] c = {’a‘,'b','c'}; System.out.println(Arrays.toString(c)); //输出 [a, b, c]多维数组
//多维数组时 int[][] bb = new int[2][3]; bb[1][2] = 3; System.out.println(Arrays.toString(bb)); //一维数组使用 toString方法 System.out.println(Arrays.deepToString(bb)); //多维数组使用deepToString方法 //输出结果 //[[I@14ae5a5, [I@7f31245a] 因为是多维数组 //[[0, 0, 0], [0, 0, 3]]常用API
属性length:返回数组长度,注意不加小括号————是属性,不是方法
常用于遍历
int a = new int[10];
for(int i=0;i<a.length;i++){
a[i] = i;
System.out.println(i);
}Arrays.sort():数组排序
int[] a = {2,1,4,6,3,5};
Arrary.sort(a);
System.out.println(Arrays.toString(a));
//输出 [1,2,3,4,5,6]支持自定义排序
使用自定义函数时,应该使用对象类型——
int的对象类型为IntegerArrays.fill(int[] a, int val):填充数组
常用于初始化数组
int[] a = {2,1,4,6,3,5};
Arrary.fill(a,100);
System.out.println(Arrays.toString(a));
//输出 [100,100,100,100,100,100]Arrays.toString():将数组转化为字符串
Arrays.deepToString():将多维数组转化为字符串
数组不可变长
字符串
与C++中字符串类型基本一样
String类
初始化
String a = "Hello World"; //去掉了 new String 是一种简写方式 String b = "My name is"; String x = b; // 存储到了相同地址 String c = b + "yxc"; // String可以通过加号拼接 String d = "My age is " + 18; // int会被隐式转化成字符串"18" String str = String.format("My age is %d", 18); // 格式化字符串,类似于C++中的sprintf String money_str = "123.45"; double money = Double.parseDouble(money_str); // String转double只读变量、不能修改——例如
String a = "Hello "; a += "World"; // 会构造一个新的字符串 不是在当前字符串上加访问String中的字符:
String str = "Hello World"; for (int i = 0; i < str.length(); i ++ ) { System.out.print(str.charAt(i)); // 只能读取,不能写入 }常用API
length():返回长度
split(String regex):分割字符串
可以加入
正则表达式indexOf(char c)、indexOf(String str):查找,找不到返回-1
存在会返回第一次出现下标
equals():判断两个字符串是否相等,注意不能直接用==
compareTo():判断两个字符串的字典序大小,负数表示小于,0表示相等,正数表示大于
startsWith():判断是否以某个前缀开头
endsWith():判断是否以某个后缀结尾
trim():去掉首位的空白字符
toLowerCase():全部用小写字符
toUpperCase():全部用大写字符
replace(char oldChar, char newChar):替换字符
replace(String oldRegex, String newRegex):替换字符串
substring(int beginIndex, int endIndex):返回[beginIndex, endIndex)中的子串
左闭右开
还有很多...
StringBuilder、StringBuffer——修改字符串长度
String不能被修改,如果打算修改字符串,可以使用StringBuilder和StringBuffer。
StringBuffer线程安全,速度较慢;StringBuilder线程不安全,速度较快。
StringBuilder sb = new StringBuilder("Hello "); // 初始化 sb.append("World"); // 拼接字符串 System.out.println(sb); for (int i = 0; i < sb.length(); i ++ ) { sb.setCharAt(i, (char)(sb.charAt(i) + 1)); // 读取和写入字符 } System.out.println(sb);
单线程使用
StringBuilder速度快多线程使用
StringBuffer更安全常用API
reverse():翻转字符串
charAt():取出单个字符
setCharAt():设置单个字符
例如:每位向后移动一位
for (int i = 0; i < sb.length(); i ++ ) {
sb.setCharAt(i, (char)(sb.charAt(i) + 1)); // 读取和写入字符
}
字符串及正则处理
JDK提供处理字符串的类有String、StringBuilder、StringBuffer和StringTokenizer共四种。
String类型
(1)与C/C++不同,字符串未使用 '\0' 作为结束符;
(2)用于存放字符的数组使用final修饰。因此,只能赋值一次且不可再更改;
(3)堆内存有一个字符串常量池,用于提高访问效率;
(4)使用字符串常量(字面量)或运算符new给String变量赋值;
(5)字符串与其他类型变量进行“+”运算,系统将自动将其他类型转换为字符串;
(6)String提供了许多字符串查找、索引、截取*、分割*、字母大小写转换和正则处理等方法。
示例:
char[] charArray ="中A1".toCharArray(); //转换为字符数组 System.out.println("中A1".length()); //输出:3 String s1 ="abc"; String s2 = new String("abc"); System.out.println(s1== s2); //输出:false System.out.println(s1.equals(s2));//输出:true StringfileName="myImage.jpg"; System.out.println(fileName.substring(fileName.indexOf('.')+1)); //输出:jpg //fileName.charAt(0)='M'; //非法语句,因为String字符串不可修改 String replaceStr = fileName.replace("jpg","png"); //利用已有串,经修改后生成新串 String[] courseArray = "Java,Java EE,Android".split(","); //字符串分割注意:双等号“==”是关系运算符,用于值相等的判定(引用类型时,为地址值相等判定);而Object的equals()方法用于判定两个对象的内容是否相同。
StringBuilder
StringBuilder表示可扩充、可修改的字符序列,是可变长的字符串,具有append()等实例方法
示例:
StringBuilder stringBuilder=new StringBuilder(); stringBuilder.append("row1").append("\n").append("row2"); //流式写法 System.out.println(stringBuilder);StringBuffer
与StringBuilder类似,StringBuffer也允许字符串在创建之后更改,但append()等方法的定义,都使用了同步修饰符synchronized,以保证在并发访问时数据的一致性,即线程安全
注意:如果不是在多线程环境,使用StringBuilder比StringBuffer速度快。
StringTokenizer
类java.util.StringTokenizer用于将某个字符串按照指定的分隔符分解成若干独立的子串。默认的分隔符是空格符、换行符、回车符、Tab符等。
示例:
String course = "Java,Java EE,Android"; StringTokenizer stringTokenizer = new StringTokenizer(course, ","); //按逗号切分 //StringTokenizer stringTokenizer = new StringTokenizer(course); //默认按空格切分 while (stringTokenizer .hasMoreTokens()) { //循环遍历 System.out.println(stringTokenizer .nextToken()); }
正则处理
正则表达式具有强大的文本匹配功能。JDK正则包java.util.regex包含模式类Pattern和匹配器类Matcher,使用正则表达式所订制的模式对字符串进行匹配。通过查看源码可知,String的正则处理实质上是调用模式类Pattern和匹配器类Matcher。
示例: 手机号以数字1开头,共11位,其正则表达式为1\d{10}。使用静态方法Pattern.matches()可测试字符串是否匹配正则表达式,封装成可供调用方法的代码如下:
public boolean checkPhoneNumber(String phoneNumber){ if(Pattern.matches("1\\d{10}",phoneNumber)){ return true; }else{ return false; } }一个使用正则表达式过滤XML文档中标签的示例代码如下:
Stringsource="<?xml version=\"1.0\"encoding=\"utf-8\"?>\n"+ "<stringxmlns=\"http://WebXml.com.cn/\">【1552764】湖北武汉湖北联通GSM卡</string>"; //从<或</开始到>结束的若干字符替换为空串。 String result =source.replaceAll("</?[^>]+>", "").trim(); //正则处理 System.out.println(result); //输出:【1552764】湖北武汉湖北联通GSM卡























