SpringBoot课——Java语法(上)


SpringBoot框架课


变量、运算符、输入与输出

类似于C#,Java的所有变量和函数都要定义在class中。

内置数据类型

img

image-20220810190851012

img

image-20220810191055659

img

img

img

在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'


一、字符串处理相关类img

二、栈操作

img

三、日期与时间类

img


部分知识

  1. String类表示的字符串是常量,一旦创建后,内容和长度都无法改变

而StringBuffer表示字符容器,其内容和长度都可以随时改修改。

在操作字符串时,如果该字符串仅用于表示数据类型,使用String类即可,

但是如果需要对字符串中的字符进行增删操作,则使用StringBuffer类。

  1. 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
         }
     ​
     }
  2. 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("处理完毕");

运行效果:img

(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编程时会大量使用

运行效果:img

注意

Java中如果是字符串的话,不能使用==来判断是否相等

因为Java中==判断是会判断两个地址是否相等

如果想要判断两个字符串是否相等,需要使用String的方法equals

 String a ="a";
 String b ="a";
 if(a.equals(b)){
  System.out.println("a");
 }

通常反过来写

 if("M".equals(op){
  System.out.println(op);
 })

img


常量

使用final修饰

 final int N = 110;

示例:

image-20220810125045102

类型转化——与C++相同

  • 显式转化:int x = (int)'A'

    • 显式转化可以从高转到低——(强制转换)——丢失超出低精度的数据

  • 隐式转化:double x =12,y = 4*3.3;int y = 12; double z = y;

    • 隐式转换只能从低到高变,从高到低变会报错————高是精度的意思

IDEA 中写输出一种简写方式

sout加补全=System.out,println

image-20220810125612761

表达式

与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中可使用方法为:

image-20220810132006912

image-20220810132048837

其中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输出

printlnprint 以及printf可以输出任意类型的东西

println会在输出末尾自动回车换行 而print则不会

image-20220810141240372

方式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);

执行结果:

image-20220811133829538

do whilewhile 只有在判断条件不成立时才不一样

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快捷命令

image-20220811134454924

使用fori

image-20220811134520301

使用foreach

image-20220811134548833

数组

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]

    • 支持自定义排序

    • image-20220812115132491

    • 使用自定义函数时,应该使用对象类型——int的对象类型为Integer

  • Arrays.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。

img

示例: 手机号以数字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卡