环境
安装JDK8并配置环境变量
jvm+核心类库=jre
jre+开发工具=jdk
Java基础运行流程,代码从上到下,从左往右,只运行一次
桌面—>新建文件夹—>新建记事本—>打开编写代码
1 2 3 4 5
| public class Hello{ public static void main(String[] args){ System.out.println("Hello luckyNwa "); } }
|
—>修改记事本名称为 Hello.java —->路径栏输入cmd回车出现终端—->
—->生成class文件—>运行
过程:源文件A.java—>javac编译—>A.class—>java运行到JVM中
在打印中加入中文发现乱码,解决
文件改成ANSI格式另存覆盖原来的utf-8 或者在javac那指令改成如下
1
| javac -encoding UTF-8 Hello.java
|

IDEA的快捷键
ctrl+/ 单行注释
/**回车 文档注释
/* */ 多行注释
shift+ctrl+enter 光标到下一行,也可以补齐;
mian 生成入口函数
alt +enter 用于前面的变量定义 比如 new Scanner(System.in);
ctrl+n 查类的说明文档 比如Math类
fori 回车直接打出循环 数组a.for回车 foreach快捷键
shift+tab 向前退一格
ctrl+alt+t 可以添for while try catch 等
命名规范
标识符(变量)规则:由字母,数字,下划线和$组成,不能以数字开头 ,不能用关键字
业内规定:
类:首字母大写,驼峰命名法
包:小写字母组成,域名倒置
变量/方法:首字母小写,驼峰命名法,需要语义化,见名知意
常量:全部大写字母,单词之间下划线隔开 要加个final修饰,不可改变
关键字:Java官方用掉的名字
数据类型
数据类型分为基本数据类型和引用数据类型(复合数据类型)
基本数据类型(四类八型)
整数类型: byte 8 short 16 int(默认) 32 long 64 数字是位数
浮点类型: float 32 单精度 double(默认) 64 双精度 float范围比long大因为它是小数的。浮点数不能用来表示精确的值,如货币
字符型: char 只有这用单引号,其他基本都是双引号 char letter = ‘A’;
布尔型 Boolean: true false(默认)
引用数据类型
它们是通过类来定义的。Java 中的引用数据类型包括:
复合数据类型有无数种,自带方法和属性,如String、Scanner、Random等
基本数据类型在内存中存储实际的值,而引用数据类型则存储对对象的引用(即内存地址)。在使用基本数据类型时,实际的值直接存储在变量中,而在使用引用数据类型时,变量存储的是对象的引用,对象本身存储在堆内存
数据类型转换
低的变高,是自动转换;高的变低必须强转,会精度损失
浮点转整需要舍弃小数位
byte到double 从低到高,byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出
1 2 3 4 5
| 低 ------------------------------------> 高
byte,short,char—> int —> long—> float —> double int i =128; byte b = (byte)i;
|
float型转换为double型
1 2 3
| float f1=100.00f; Float F1=new Float(f1); double d1=F1.doubleValue();
|
简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)
而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据
补充
string 转 int
int 转String
类似
1 2 3
| String s1 = String.valueOf(i); String s2 = Integer.toString(i); String s3 = "" + i;
|
运算符
算术运算符
+、-、*、/、% 、++、– (%取余5%2=1)
关系运算符
== 、!=、>、<、>=、<=
位运算符
& |(计算二进制的,用处少)
7 二进制过程—> 7/2 =3 1 3/2=1 1 1/2= 1 0111 7的二进制结果倒着余数 111
9 二进制过程—> 9/2=4 1 4/2=2 0 2/2=1 0 1/2= 1 1001 结果倒着余数 1001
0001 7&9结果1 &必须2个是1才是1
逻辑运算符
&&(逻辑与,2真才真,也叫短路运算符,1假则不会继续下个判断了) 、||(逻辑或,1真就真)、 !(逻辑非)
赋值运算符
=、+=,-=..(c-=a 等价于 c=c-a 其他同理)
条件运算符
条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
1 2 3
| int a = 10; int b = 20; int max = a < b ? b : a;
|
条件
Java 中的条件语句允许 程序 根据条件的不同执行不同的代码块
1 2 3 4 5 6 7 8 9
| if(布尔表达式 1){ }else if(布尔表达式 2){ }else if(布尔表达式 3){ }else { }
|
上面可以各种用
switch case
判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
1 2 3 4 5 6 7 8 9 10 11
| switch(expression){ case value : break; case value : break; default : }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Test { public static void main(String args[]){ int i = 2; switch(i){ case 0: System.out.println("0"); case 1: System.out.println("1"); case 2: System.out.println("2"); default: System.out.println("default"); } } }
|
匹配成功后,从当前 case 开始,后续所有 case 的值都会输出
2
default
如果i是6,都匹配不到则返回默认的default里的值,一般匹配到就break打断了
循环
Java中有三种主要的循环结构:
java5引入foreach—>数组的增强型 for 循环 数组a.for回车快速生成
1 2 3 4 5 6 7 8
| public class Demo1 { public static void main(String[] args) { int[] numbers = {10, 20, 30, 40, 50}; for (int item : numbers) { System.out.println(item); } } }
|
配合的关键字
break主要用于停止,整个循环语句或者 switch 语句,循环语句后面的代码还会运行
continue用于循环里面让程序跳过当前循环,立刻进入下一次的循环
return用于返回方法类型指定的值也可以是对象,还能可以结束后面代码的执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Demo1 { public static void main(String[] args) { int[] numbers = {10, 20, 30, 40, 50}; for (int item : numbers) {
System.out.print(item); System.out.print(","); if (item == 10) {
return; } } System.out.println("哈哈"); } }
|
总结
for和while都被称为前置判断循环 do..while是后置判断循环
while和do while都属于不确定次数的循环语句
for 是属于确定次数的循环语句
数组
数组的创建
入口函数那是推荐main(String[] args) 或者写main(String args[])
声明
1 2 3 4
| dataType[] arrayRefVar; 或 dataType arrayRefVar[]; arrayRefVar = new dataType[arraySize];
|
创建数组
1 2 3
| dataType[] arrayRefVar = new dataType[arraySize]; dataType[] arrayRefVar = new dataType[]{value0, value1, ..., valuek}; dataType[] arrayRefVar = {value0, value1, ..., valuek};
|
一维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Demo1 { public static void main(String[] args) { int size = 5; double[] myList = new double[size]; myList[0] = 5.6; myList[1] = 4.5; myList[2] = 3.3; myList[3] = 13.2; myList[4] = 4.0; double total = 0; for (int i = 0; i < size; i++) { total += myList[i]; } System.out.println("总和为: " + total); double max = myList[0]; for (int i = 1; i < myList.length; i++) { if (myList[i] > max) max = myList[i]; } System.out.println("Max is " + max); System.out.println("-------------------"); int[] arr = {1, 2, 3, 4, 5}; for (int x : arr) { System.out.println(x); } } }
|
二维数组
1
| type[][] typeName = new type[typeLength1][typeLength2];
|
type 可以为基本数据类型和复合数据类型,typeLength1 和 typeLength2 必须为正整数,typeLength1 为行数,typeLength2 为列数
1
| int[][] a = new int[2][3];
|
a 可以看成一个两行三列的数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Demo1 { public static void main(String[] args) { String[][] s = new String[2][]; s[0] = new String[2]; s[1] = new String[3]; s[0][0] = new String("Good"); s[0][1] = new String("Luck"); s[1][0] = new String("to"); s[1][1] = new String("you"); s[1][2] = new String("!");
for (String[] strings : s) { for (String string : strings) { System.out.print(string.concat("\t")); } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Demo1 { public static void main(String[] args) { String[] stu1 = {"张三", "Jx202211", "男", "22"}; String[] stu2 = {"李四", "Jx202212", "女", "21"}; String[] stu3 = {"王五", "Jx202213", "男", "25"}; String[] stu4 = {"小六", "Jx202214", "女", "20"}; String[][] stu = {stu1, stu2, stu3, stu4}; for (int i = 0; i < stu.length; i++) { for (int j = 0; j < stu[i].length; j++) { System.out.print(stu[i][j] + "\t"); } System.out.println(); } } }
|
函数(方法)
函数是一段具备特定功能的、高度封装的代码块
函数声明:
1 2 3 4 5 6
| 修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
|
1、修饰符 public static 公开的 静态的
2、返回值类 void 表返回值为null,就不需要return,其他都需要
3、函数名 小驼峰命名
4、参数列表
5、方法体 要执行的代码块

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class Demo1 { public static void main(String[] args) { Demo1.nPrintln("lucky", 2); Demo1 demo1 = new Demo1(); System.out.println("最大值是" + demo1.max(1, 2)); System.out.println("最大值是" + demo1.max(11.2, 32.2)); printMax(new double[]{1, 2, 3}); printMax(new double[]{}); }
public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) { System.out.println(message); } }
public int max(int num1, int num2) { return num1 > num2 ? num1 : num2; }
public Double max(Double num1, Double num2) { return num1 > num2 ? num1 : num2; }
public static void printMax(double... numbers) { if (numbers.length == 0) { System.out.println("No argument passed"); return; } double result = numbers[0]; for (int i = 1; i < numbers.length; i++) { if (numbers[i] > result) { result = numbers[i]; } } System.out.println("The max value is " + result); } }
|
形参与实参:函数声明里就是形参,而调用那里输入则是实参
返回值:看声明里返回值类,void则没有返回值,如int则返回整型n,如果是类,返回一个对象类
函数的递归:即函数里调用函数自己
变量作用域:方法内声明的变量(局部变量),方法外不可用
方法重载:同一类中方法名相同,参数数量和类型不同。构造方法(对象里的)就可以利用重载
对象
世界万物皆对象,对象的特点是属性、对象的行为是方法,对象的行为必须是自发的
特征
封装
私有化属性并设置公有的get、set方法 IDEA右键—>生成—选择需要的
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问
比如该类是公开的属性,那么外部new这个对象时候便可以直接.属性去修改,现在我们封装了它无法直接修改需要调用set方法去修改,比如年龄想修改1000岁是不正常的,我们便可以再set方法中加逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class Lucky { private String name;
public Lucky() {
}
public Lucky(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String toString() { return "Lucky{" + "name='" + name + '\'' + '}'; } }
|
1 2 3 4 5 6 7 8 9
| public class Demo1 { public static void main(String[] args) { Lucky name = new Lucky("小维"); System.out.println(name); Lucky name2 = new Lucky(); name2.setName("小米"); System.out.println(name2); } }
|
结果:
Lucky{name=’小维’}
Lucky{name=’小米’}
this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突
构造函数
是一个没有返回值,并且函数名和类型相同的函数,在对象实例化的一瞬间就会执行,利用构造函数的参数,对属性进行赋值
继承
继承就是子类继承父类的属性和方法 苹果是水果可以继承水果类 食草动物是动物可以继承动物类
必须满足is-a关系 父类更通用 子类更具体

关键字是extends 写在类名后面
一个类只能继承一个抽象类, 继承不可滥用,牵一发而动全身,父类改变一次,其他全部受到影响,即耦合性过高,
继承一般继承Java官方的类
1 2 3 4 5
| class 父类 { }
class 子类 extends 父类 { }
|
现在有3个类如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Penguin { private String name; private int id;
public Penguin(String myName, int myid) { name = myName; id = myid; }
public void eat() { System.out.println(name + "正在吃"); }
public void sleep() { System.out.println(name + "正在睡"); }
public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Mouse { private String name; private int id;
public Mouse(String myName, int myid) { name = myName; id = myid; }
public void eat() { System.out.println(name + "正在吃"); }
public void sleep() { System.out.println(name + "正在睡"); }
public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Demo1 { public static void main(String[] args) { Penguin penguin = new Penguin("企鹅", 1); penguin.eat(); penguin.sleep(); penguin.introduction(); Mouse mouse = new Mouse("老鼠", 2); mouse.eat(); mouse.sleep(); mouse.introduction(); } }
|
会发现代码存在重复,导致代码量大且臃肿,而且维护性不高(主要表现是后期需要修改的时候,需要修改很多的代码,容易出错)
要从根本上解决这两段代码的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Animal { private String name; private int id; public Animal(String myName, int myid) { name = myName; id = myid; } public void eat(){ System.out.println(name+"正在吃"); } public void sleep(){ System.out.println(name+"正在睡"); } public void introduction() { System.out.println("大家好!我是" + id + "号" + name + "."); } }
|
改造子类,extends单继承,子类只能有一个父类,可以多重继承比如a给b继承,b给c继承,没用过。子类不继承父类的构造器
1 2 3 4 5
| public class Penguin extends Animal{ public Penguin(String myName, int myid) { super(myName, myid); } }
|
1 2 3 4 5
| public class Mouse extends Animal { public Mouse(String myName, int myid) { super(myName, myid); } }
|
关键字 super :放在代码里 用来子类给父类的构造函数的参数传参,还能调用父类的方法 ,不过继承就有父方法了
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器
继承关系下
首先,会调用父类的构造函数。如果子类构造函数的第一行没有显式调用父类构造函数(通过 super()),则会自动调用父类的无参构造函数。如果父类没有无参构造函数,并且子类没有显式调用父类的其他构造函数,则编译器会报错
然后,执行父类的构造函数体
接着,再执行子类的构造函数。如果子类构造函数的第一行没有显式调用其他构造函数(通过 this() 或 super()),则会自动调用父类的无参构造函数,然后执行子类的构造函数体
最后,执行子类的构造函数体
重写(Override)
子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!
父类的方法,子类写的一模一样,最终执行的是子类的方法
重写规则:修饰符不能强于父类,返回值类型、方法名、参数列表必须一样
重载(overloading)
在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同
多态
多态指同一个事物能呈现出多种形态的能力 多态是继承的一种体现
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现
多态就是同一个接口,使用不同的实例而执行不同操作
多态存在的三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象:Parent p = new Child();

AnimalT能呈现出多种形态的能力
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Demo1 { public static void main(String[] args) { AnimalT a = new Lion(); a.eat(); a.sleep(); } }
abstract class AnimalT { abstract void eat(); abstract void sleep();
}
class Lion extends AnimalT { public void eat() { System.out.println("狮子吃"); } public void sleep() { System.out.println("狮子睡"); } }
class Tiger extends AnimalT { public void eat() { System.out.println("老虎吃"); } public void sleep() { System.out.println("老虎睡"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Animal { public void makeSound() { System.out.println("动物发出声音"); } }
class Dog extends Animal { @Override public void makeSound() { System.out.println("狗发出汪汪声"); } }
class Cat extends Animal { @Override public void makeSound() { System.out.println("猫发出喵喵声"); } }
public class Main { public static void main(String[] args) { Animal animal1 = new Dog(); Animal animal2 = new Cat();
animal1.makeSound(); animal2.makeSound(); } }
|
这就是多态的体现,通过父类的引用调用被子类重写的方法
接口
接口并不是类,类描述对象的属性和方法。接口则包含类要实现的方法
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类
接口:没有方法体的方法的集合
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(JDK8后default也行,其他修饰符会报错)
- JDK 1.8 以后,接口里可以有静态方法和方法体
implements关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
1 2 3 4 5 6 7 8 9 10 11
| public interface A { void eat(); void sleep(); }
public interface B { void show(); }
public class C implements A,B { }
|
有方法体的方法 被称为 实例方法
没方法体的方法 被称为 抽象方法
包装类
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类

这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包
1 2 3 4 5 6 7
| public class Test{ public static void main(String[] args){ Integer x = 5; x = x + 10; System.out.println(x); } }
|
修饰符
访问控制修饰符
Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
- default (无修饰): 本类、同一包的类可见
- private : 私有的 能且仅能在本类中使用 注意:不能修饰类(private class Demo1 )错误
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 本类、子类、同一包的类可见 注意:不能修饰类(外部类)
static
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据
它的特性:只会在类加载的时候执行一次。
final
final 表示”最后的、最终的”含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值
final修饰类中的属性或者变量 无论属性是基本类型还是引用类型,final所起的作用都是变量里面存放的”值”不能变,这个值,对于基本类型来说,变量里面放的就是实实在在的值,而引用类型变量里面放的是个地址,所以用final修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意
final 修饰符通常和 static 修饰符一起使用来创建类常量。
1 2 3 4
| public class MyClass { public static int count = 0; public static final int MAX_SIZE = 100; }
|
访问
1 2 3
| MyClass.count = 10; MyClass obj = new MyClass(); obj.count = 20;
|
final 属性 声明变量时可以不赋值,而且一旦赋值就不能被修改了,用来new的那个对象里有final修饰的属性那个属性必须赋值
final 方法 可以被子类继承,但是不能被子类重写。声明 final 方法的主要目的是防止该方法的内容被修改
final 类 不能被继承
abstract(抽象类)
抽象类不能用来实例化对象
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误
抽象类可以包含抽象方法和非抽象方法
1 2 3 4 5 6 7
| abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); public abstract void changeColor(); }
|
抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供
抽象方法不能被声明成 final 和 static
如果一个类包含抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法
继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也必须声明为抽象类
构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法
抽象方法的声明以分号结尾,例如:public abstract sample();
1 2 3 4 5 6 7 8 9 10
| public abstract class SuperClass{ abstract void m(); }
class SubClass extends SuperClass{ void m(){ ......... } }
|
synchronized
synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
1 2 3
| public synchronized void showDetails(){ ....... }
|
枚举类
枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一年的 12 个月份,一个星期的 7 天,方向有东南西北等—>场景:颜色(红黄蓝绿…)、星期、反射做多个oss桶时候
常量类是指一组声明为静态的、不可改变的常量变量,它们通常用于定义一些全局性的常量,如数学常数π、还有一些不变的值,项目中必定有一个常量类,final关键字,表示这些变量不能被修改—> 场景:分页的当前页、限制页数、返回的数据成功、失败…
Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割
1 2 3 4 5 6 7 8 9 10
| enum Color { RED, GREEN, BLUE; private Color() { System.out.println("Constructor called for : " + this.toString()); } public void colorInfo() { System.out.println("枚举的方法"); } }
|
每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的,所以可以 类名.名称
- values() 返回枚举类中所有的值。
- ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
- valueOf()方法返回指定字符串值的枚举常量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class Demo1 { public static void main(String[] args) { Color c1 = Color.RED; System.out.println(c1); for (Color myVar : Color.values()) { System.out.println(myVar); } Color myVar = Color.BLUE; switch (myVar) { case RED: System.out.println("红色"); break; case GREEN: System.out.println("绿色"); break; case BLUE: System.out.println("蓝色"); break; } Color[] arr = Color.values(); for (Color col : arr) { System.out.println(col + " at index " + col.ordinal()); } System.out.println(Color.valueOf("RED")); Color green = Color.GREEN; green.colorInfo(); Color red = Color.RED; red.colorInfo(); } }
|
工作中的写法1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public enum ErrorCode { OK(0) { public String getDescription() { return "成功"; } }, ERROR_A(100) { public String getDescription() { return "错误A"; } }, ERROR_B(200) { public String getDescription() { return "错误B"; } }; private int code; private ErrorCode(int number) { this.code = number; } public int getCode() { return code; } public abstract String getDescription(); }
|
写法2 效果和调用一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public enum ErrorCodeEn { OK(0, "成功"), ERROR_A(100, "错误A"), ERROR_B(200, "错误B"); ErrorCodeEn(int number, String description) { this.code = number; this.description = description; } private int code; private String description; public int getCode() { return code; } public String getDescription() { return description; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo1 { public static void main(String[] args) { System.out.println(ErrorCodeEn.OK.getCode()); System.out.println(ErrorCodeEn.ERROR_A.getCode()); System.out.println(ErrorCodeEn.ERROR_B.getCode()); System.out.println(ErrorCodeEn.OK.getDescription()); System.out.println(ErrorCodeEn.ERROR_A.getDescription()); System.out.println(ErrorCodeEn.ERROR_B.getDescription());
} }
|
补充
面向对象与面向过程区别
面向过程:只关注事情本身的完成,不关注谁去做,就像大象塞进冰箱,不管是谁把冰箱打开,谁把大象弄进去
面向对象:更多关注 谁去做事情 各有各的好处
对象的生命周期
对象的出生:一旦被声明被赋值之后 对象即出现
对象的销毁:当该对象没有被指向 就会被自动销毁
String a;这是空,没有对象,所以没有出生和销毁
IO流
IO 流:按照流动的方向,以内存为基准,分为输入 input 和输出 output ,即流向内存是输入流,流出内存的输出流
(1)明确要操作的数据是数据源还是数据目的(也就是要读还是要写)
(2)明确要操作的设备上的数据是字节还是文本
(3)明确数据所在的具体设备
(4)明确是否需要额外功能(比如是否需要转换流、高效流等)
输入流(读数据 硬盘—->内存)、输出流(写数据 内存—>硬盘)
分类:
1.字节流:字节流又分为字节输入流、字节输出流 2.字符流:字符流由分为字符输入流、字符输出流
字符流的由来:因为数据编码的不同,字节流直接读中文会乱码 字符流 = 字节流 + 编码表
数据流向内存就是输入流,流出内存就是输出流,根据数据的类型分为
字节流和字符流,如名字的为单位
字节流对应的输入流 InputStream 输出流 OutputStream
字符流对应的输入流 Reader 输出流 Writer
超类(父类)以这四个名称结尾都是它的子类
比如常见的 FileInputStream 文件输入流
1 个字符=2 个字节
字节流适合读取视频、音乐、图片等二进制文件,字符流比较适合读取纯文本文件
字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据
File 类
java.io.File 类是专门对文件进行操作的类,只能对文件本身进行操作,不能对文件进行读和写也就是输入和输出
File 类构造方法不会给你检验这个文件或文件夹是否真实存在,因此无论该路径下是否存在文件或者目录,都不影响 File 对象的创建。
下面一个测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| package com.nwa;
import org.junit.Test;
import java.io.*;
public class FileDemo { @Test public void fun1() throws IOException { File f = new File("C:\\Users\\FF\\Desktop\\1.txt"); if (!f.exists()) { System.out.println("是否创建:"+f.createNewFile()); } System.out.println("是否创建:"+f.createNewFile()); System.out.println("文件绝对路径:"+f.getAbsolutePath()); System.out.println("文件构造路径:"+f.getPath()); System.out.println("文件名称:"+f.getName()); System.out.println("文件长度:"+f.length()+"字节"); System.out.println("文件:"+f.isFile()); System.out.println("目录:"+f.isDirectory());
}
@Test public void testDemo2() { File f2= new File("newDira");
File f4= new File("newDira\\newDirb");
}
@Test public void demo3() { File file = new File("E:\\other\\study\\学习sp\\实用篇"); printFile(file); } public static void printFile(File file) {
if(!file.isDirectory()){ return; } File[] files = file.listFiles(); for (File f: files) { if(f.isDirectory()){ printFile(f); }else { System.out.println(f.getName()); }
} }
public static void demo2(){ try { File file1 = new File("D:\\workspace\\a.txt"); long flen=file1.length(); System.out.println("源文件的大小是"+flen+"字节"); FileInputStream fis = new FileInputStream(file1); File file2 = new File("D:\\workspace\\b.txt"); FileOutputStream fos = new FileOutputStream(file2); byte[] bytes = new byte[1024]; int len = 0; long readSize=0; while ((len = fis.read(bytes)) != -1) { fos.write(bytes,0,len); fos.flush(); readSize+=len; if (readSize== flen) { break; } } System.out.println("读的大小"+readSize+"字节"); } catch (Exception e) { e.printStackTrace(); } }
public static void demo1() { File file = new File("E:\\1.txt"); File file1 = new File("E:\\222.txt"); try { FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(file1); BufferedInputStream bis = new BufferedInputStream(fis); byte[] bytes = new byte[1024]; while (bis.read(bytes) != -1) { fos.write(bytes); fos.flush(); System.out.println("aaaa"); }
} catch (Exception e) { e.printStackTrace(); }
} }
|
FileOutputStream
1
| FileOutputStream outputStream = new FileOutputStream("abc.txt");
|
这行代码做了下面的事情
1、调用系统功能去创建文件【输出流对象才会自动创建】
2、创建outputStream对象
3、把foutputStream对象指向这个文件
创建输出流对象的时候,系统会自动去对应位置创建对应文件,而创建输出流对象的时候,文件不存在则会报 FileNotFoundException 异常,也就是系统找不到指定的文件异常。
当你创建一个流对象时,必须直接或者间接传入一个文件路径。比如现在我们创建一个 FileOutputStream 流对象,在该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据
为什么是输入流呢
1、因为流是相对于内存来说的,现在 abc.txt 就是要保存到磁盘里面的文本,就是说从内存—->磁盘,那必须是输出流,用 FileWrite 和 FileOutputStream 都可以
2、传入路径时候是它的一种构造方法,不会继续写到文本中,所以用它的另外的构造函数即可解决这个问题。
public FileOutputStream(File file, boolean append) 一般不需要用这个,因为文件创建,输出流自动会帮我们生成,没必要多此一举暂时
public FileOutputStream(String name, boolean append) true 表示追加数据
Windows 系统里,每行结尾是 回车+换行 ,即\r\n;
Unix 系统里,每行结尾只有 换行 ,即\n;
Mac 系统里,每行结尾是 回车 ,即\r。从 Mac OS X 开始与 Linux 统一。
流进内存的,输入流
1、 **FileInputStream(File file)**: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。
2、 **FileInputStream(String name)**: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。
当你创建一个输入流对象时,必须传一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException
使用字节数组读取:read(byte[] b) 效率更高
1 2 3 4
| int len = 0 ; byte[] bys = new byte[1024]; while ((len = inputStream.read(bys)) != -1) { System.out.println(new String(bys,0,len));
|
Reader
字符输入流的所有类的超类 输入流
FileWriter
写出字符到文件的便利类 输出流
//关闭资源时,与 FileOutputStream 不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
// fw.close();
关闭 close 和刷新 flush
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。
flush :刷新缓冲区,流对象可以继续使用。清空缓冲区的数据流
close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
缓冲流
1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内。
2、通过缓冲区的 read()方法从缓冲区获取具体的字符数据,这样就提高了效率。
3、如果用 read 方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了 readLine()功能。
也就是说在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统 IO 次数,从而提高读写的效率。
缓冲书写格式为 BufferedXxx,按照数据类型分类:
字节缓冲流:BufferedInputStream,BufferedOutputStream
字符缓冲流:BufferedReader,BufferedWriter
构造方法
public BufferedInputStream(InputStream in) :创建一个新的缓冲输入流,注意参数类型为 InputStream。
**public BufferedOutputStream(OutputStream out)**: 创建一个新的缓冲输出流,注意参数类型为 OutputStream。
BufferedReader:public String readLine(): 读一行数据。 读取到最后返回 null,就这个特别一点,判断条件都需要修改了
BufferedWriter:public void newLine(): 换行,由系统属性定义符号。
转换流
简单一点的说就是:
编码:字符(能看懂的)–字节(看不懂的)
解码:字节(看不懂的)–>字符(能看懂的)
1 2 3 4 5 6 7 8
| String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组 byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
编码:把看得懂的变成看不懂的 String -- byte[]
解码:把看不懂的变成看得懂的 byte[] -- String
|
字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
在 java 开发工具 IDEA 中,使用 FileReader 读取项目中的文本文件。由于 IDEA 的设置,都是默认的 UTF-8 编码,所以没有任何问题。但是,当读取 Windows 系统中创建的文本文件时,由于 Windows 系统的默认是 GBK 编码,就会出现乱码。
转换流 java.io.InputStreamReader,是 Reader 的子类,从字面意思可以看出它是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。
构造方法
InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。
构造代码如下:
1 2
| InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt")); InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");
|
OutputStreamWriter同理
案例 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| package com.nwa;
import org.junit.Test;
import java.io.*;
public class FileDemo { @Test public void fun1() throws IOException { File f = new File("C:\\Users\\FF\\Desktop\\1.txt"); if (!f.exists()) { System.out.println("是否创建:"+f.createNewFile()); } System.out.println("是否创建:"+f.createNewFile()); System.out.println("文件绝对路径:"+f.getAbsolutePath()); System.out.println("文件构造路径:"+f.getPath()); System.out.println("文件名称:"+f.getName()); System.out.println("文件长度:"+f.length()+"字节"); System.out.println("文件:"+f.isFile()); System.out.println("目录:"+f.isDirectory());
}
@Test public void testDemo2() { File f2= new File("newDira");
File f4= new File("newDira\\newDirb");
}
@Test public void demo3() { File file = new File("E:\\other\\study\\学习sp\\实用篇"); printFile(file); } public static void printFile(File file) {
if(!file.isDirectory()){ return; } File[] files = file.listFiles(); for (File f: files) { if(f.isDirectory()){ printFile(f); }else { System.out.println(f.getName()); }
} }
public static void demo2(){ try { File file1 = new File("D:\\workspace\\a.txt"); long flen=file1.length(); System.out.println("源文件的大小是"+flen+"字节"); FileInputStream fis = new FileInputStream(file1); File file2 = new File("D:\\workspace\\b.txt"); FileOutputStream fos = new FileOutputStream(file2); byte[] bytes = new byte[1024]; int len = 0; long readSize=0; while ((len = fis.read(bytes)) != -1) { fos.write(bytes,0,len); fos.flush(); readSize+=len; if (readSize== flen) { break; } } System.out.println("读的大小"+readSize+"字节"); } catch (Exception e) { e.printStackTrace(); } }
public static void demo1() { File file = new File("E:\\1.txt"); File file1 = new File("E:\\222.txt"); try { FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(file1); BufferedInputStream bis = new BufferedInputStream(fis); byte[] bytes = new byte[1024]; while (bis.read(bytes) != -1) { fos.write(bytes); fos.flush(); System.out.println("aaaa"); }
} catch (Exception e) { e.printStackTrace(); }
} }
|
案例 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
| package com.nwa;
import org.junit.Test; import org.omg.CORBA.PUBLIC_MEMBER;
import java.io.*;
public class IoDemo { @Test public void demo1() throws IOException { FileOutputStream fos = new FileOutputStream("a.txt", true); fos.write(97); fos.write(("我要吃汉堡").getBytes()); fos.close(); FileWriter fileWriter = new FileWriter("b.txt"); fileWriter.write("ss"); fileWriter.close();
FileOutputStream fos2 = new FileOutputStream("a2.txt"); byte[] b = "abcde".getBytes(); fos2.write(b, 2, 2); fos2.close(); }
@Test public void delTxt() { new File("a.txt").delete(); }
@Test public void arrDemo() throws IOException { FileOutputStream fos = new FileOutputStream("fos.txt"); byte[] words = {97, 98, 99, 100, 101}; for (int i = 0; i < words.length; i++) { fos.write(words[i]); fos.write("\r\n".getBytes()); } fos.close(); }
@Test public void inputS() throws IOException { File file = new File("a2.txt"); FileInputStream fis = new FileInputStream(file);
int len; byte[] b = new byte[2]; while ((len = fis.read(b)) != -1) { System.out.println(new String(b, 0, len)); } fis.close(); }
@Test public void copyPic() throws IOException { FileInputStream fis = new FileInputStream("C:\\Users\\FF\\Desktop\\6.png"); FileOutputStream fos = new FileOutputStream("1.png"); byte[] b = new byte[1024]; int len; while ((len = fis.read(b)) != -1) { fos.write(b, 0, len); } fos.close(); fis.close(); }
@Test public void readI() throws IOException { FileInputStream fis = new FileInputStream("1.txt"); int len; byte[] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1) { System.out.println((char) len); System.out.print(new String(bytes, 0, len)); } FileReader fr = new FileReader("1.txt"); int len2; while ((len2 = fr.read()) != -1) { System.out.print((char) len2); } }
@Test public void copyText() throws IOException{ FileWriter fileWriter = new FileWriter("66.md"); FileReader fileReader = new FileReader("E:\\后端代码接收解析.md"); char[] c=new char[1024]; int len; while ((len = fileReader.read(c)) != -1) { fileWriter.write(c, 0, len);
} fileWriter.flush(); fileWriter.close(); fileReader.close(); }
@Test public void Buff1() throws IOException{ long start = System.currentTimeMillis(); FileOutputStream fos = new FileOutputStream("ps2015.zip"); FileInputStream fis = new FileInputStream("E:\\other\\装机必备软件\\必备软件\\ps2015.zip"); byte[] bytes = new byte[1024]; int len; while ((len = fis.read(bytes)) != -1) { fos.write(bytes, 0, len); } fis.close(); fos.close(); long end = System.currentTimeMillis(); System.out.println("普通流复制时间:"+(end - start)+" 毫秒"); } @Test public void Buff2() throws IOException{ long start = System.currentTimeMillis(); BufferedOutputStream fos =new BufferedOutputStream(new FileOutputStream("ps2015.zip")) ; BufferedInputStream fis =new BufferedInputStream(new FileInputStream("E:\\other\\装机必备软件\\必备软件\\ps2015.zip")) ; byte[] bytes = new byte[1024]; int len; while ((len = fis.read(bytes)) != -1) { fos.write(bytes, 0, len); } fis.close(); fos.close(); long end = System.currentTimeMillis(); System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒"); }
@Test public void BuffRead() throws IOException { BufferedReader br = new BufferedReader(new FileReader("b.txt")); System.out.println(br.readLine()); String len=null; while ((len = br.readLine()) != null) { System.out.println((len)); } br.close(); }
@Test public void transform() throws IOException{ String FileName = "C:\\Users\\FF\\Desktop\\1.txt"; InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName)); InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK"); int read; while ((read = isr.read()) != -1) { System.out.print((char)read); } isr.close();
while ((read = isr2.read()) != -1) { System.out.print((char)read); } isr2.close(); }
}
|
异常处理
异常处理是一种重要的编程概念,用于处理程序执行过程中可能出现的错误或异常情况
必须捕获的异常,包括Exception及其子类,但不包括RuntimeException及其子类,这种类型的异常称为Checked Exception
不需要捕获的异常,包括Error及其子类,RuntimeException及其子类
- 数值类型的格式错误————NumberFormatException
- 要打开的文件不存在————FileNotFoundException
- 空指针————NullPointerException————对某个
null的对象调用方法或字段
- 数组索引越界————ArrayIndexOutOfBoundsException
- 数据库表不存在
- 向方法传递了一个不合法或不正确的参数
- 无法加载某个Class————NoClassDefFoundError
- 栈溢出————StackOverflowError
错误: 错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error
异常类有两个主要的子类:IOException 类和 RuntimeException 类

捕获异常
如果不捕获异常,就需要抛出异常,直到有人捕获或者最高一级
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。ctrl+alt+t
throws 是写在类那里——————–throw 是直接在方法里面抛出
try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
1 2 3 4 5 6 7 8
| try { }catch(ExceptionName e1) { }
|
throw 关键字用于在代码中抛出异常,而 throws 关键字用于在方法声明中指定可能会抛出的异常类型
当方法内部throws抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class Demo1 { public static void main(String[] args) {
try { readFile("D:\\1.txt"); System.out.println("找到了"); } catch (IOException e) { throw new RuntimeException(e); }
}
public static void checkNumber(int num) { if (num < 0) { throw new IllegalArgumentException("Number must be positive"); } }
public static void readFile(String filePath) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(filePath)); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } reader.close(); } }
|
JDK7 之后,Java 新增的 try-with-resource 语法结构,旨在自动管理资源,确保资源在使用后能够及时关闭,避免资源泄露 。
1 2 3 4 5
| try (resource declaration) { } catch (ExceptionType e1) { }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Demo1 { public static void main(String[] args) { String line; try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { while ((line = br.readLine()) != null) { System.out.println("Line =>" + line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } } }
|
结果:IOException in try block =>test.txt (系统找不到指定的文件。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Demo1 { public static void main(String[] args) { BufferedReader br = null; String line; try { System.out.println("Entering try block"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) { System.out.println("Line =>" + line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } finally { System.out.println("Entering finally block"); try { if (br != null) { br.close(); } } catch (IOException e) { System.out.println("IOException in finally block =>" + e.getMessage()); } } } }
|
全局异常处理器
在应用程序中,当抛出异常时,如果没有特定的异常处理器来处理该异常,就会尝试使用全局异常处理器来处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @RestControllerAdvice public class RRExceptionHandler { private Logger logger = LoggerFactory.getLogger(getClass());
@ExceptionHandler(RRException.class) public R handleRRException(RRException e){ R r = new R(); r.put("code", e.getCode()); r.put("msg", e.getMessage());
return r; } @ExceptionHandler(NoHandlerFoundException.class) public R handlerNoFoundException(Exception e) { logger.error(e.getMessage(), e); return R.error(404, "路径不存在,请检查路径是否正确"); } @ExceptionHandler(DuplicateKeyException.class) public R handleDuplicateKeyException(DuplicateKeyException e){ logger.error(e.getMessage(), e); return R.error("数据库中已存在该记录"); } @ExceptionHandler(AuthorizationException.class) public R handleAuthorizationException(AuthorizationException e){ logger.error(e.getMessage(), e); return R.error("没有权限,请联系管理员授权"); } @ExceptionHandler(Exception.class) public R handleException(Exception e){ logger.error(e.getMessage(), e); return R.error(); } }
|
自定义异常类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class RRException extends RuntimeException { private static final long serialVersionUID = 1L; private String msg; private int code = 500;
public RRException(String msg) { super(msg); this.msg = msg; } public RRException(String msg, Throwable e) { super(msg, e); this.msg = msg; } public RRException(String msg, int code) { super(msg); this.msg = msg; this.code = code; } public RRException(String msg, int code, Throwable e) { super(msg, e); this.msg = msg; this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }
|
API
Random(常用)
获取随机数
1 2 3 4 5 6 7 8 9 10 11
| public class Demo1 { public static void main(String[] args) { Random random = new Random(); int randomValue1 = random.nextInt(2); System.out.println(randomValue1); int randomValue2 = random.nextInt(90) + 10; System.out.println(randomValue2); int randomValue3 = random.nextInt(1000) - 500; System.out.println(randomValue3); } }
|
Scanner
获取控制台输入的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Demo1 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("请输入名称:"); String name = scanner.nextLine(); System.out.println("请输入密码:"); String pwd = scanner.nextLine(); System.out.println(name + "--左名称右密码--" + pwd); System.out.println("请输入整数n:"); int i = 0; if (scanner.hasNextInt()) { i = scanner.nextInt(); System.out.println("整数数据:" + i); } else { System.out.println("输入的不是整数!"); } System.out.println("i为" + i); scanner.close(); } }
|
Date
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Demo1 { public static void main(String[] args) { Date date = new Date(); System.out.printf("全部日期和时间信息:%tc%n", date); System.out.printf("年-月-日格式:%tF%n", date); System.out.printf("月/日/年格式:%tD%n", date); System.out.printf("HH:MM:SS PM格式(12时制):%tr%n", date); System.out.printf("HH:MM:SS格式(24时制):%tT%n", date); System.out.printf("HH:MM格式(24时制):%tR%n", date); System.out.printf("%tY-%tm-%td %tH:%tM:%tS %tZ%n", date, date, date, date, date, date, date); System.out.println("-----------------------------------"); Date dNow = new Date(); SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS"); String format = ft.format(dNow); System.out.println("当前时间为: " + format); } }
|
Calendar
Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可
我们如何才能设置和获取日期数据的特定部分呢,比如说小时,日,或者分钟? 我们又如何在日期的这些部分加上或者减去值呢? 答案是使用Calendar 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Demo1 { public static void main(String[] args) { String months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int year; GregorianCalendar gcalendar = new GregorianCalendar(); System.out.print("Date: "); System.out.print(months[gcalendar.get(Calendar.MONTH)]); System.out.print(" " + gcalendar.get(Calendar.DATE) + " "); System.out.println(year = gcalendar.get(Calendar.YEAR)); System.out.print("Time: "); System.out.print(gcalendar.get(Calendar.HOUR) + ":"); System.out.print(gcalendar.get(Calendar.MINUTE) + ":"); System.out.println(gcalendar.get(Calendar.SECOND));
if (gcalendar.isLeapYear(year)) { System.out.println("当前年份是闰年"); } else { System.out.println("当前年份不是闰年"); } } }
|
Math
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用
1 2 3 4 5 6 7 8 9 10 11
| public class Test { public static void main (String []args) { System.out.println("返回两个参数中的最大值:" + Math.max(1, 2)); System.out.println("返回两个参数中的最小值:" + Math.min(0, 3)); System.out.println("60度的正切值:" + Math.tan(Math.PI / 3)); System.out.println("1的反正切值: " + Math.atan(1)); System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI / 2)); System.out.println(Math.PI); } }
|
String
String 类是不可改变的final修饰,所以你一旦创建了 String 对象,那它的值就无法改变
如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类
String 创建的字符串存储在公共池中,而 new 创建的字符串对象在堆上
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Demo1 { public static void main(String[] args) { String s1 = "Runoob"; String s2 = "Runoob"; String s3 = s1; String s4 = new String("Runoob"); String s5 = new String("Runoob"); System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1.equals(s3)); System.out.println(s4 == s5); System.out.println(s4.equals(s5)); } }
|

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class Demo1 { public static void main(String[] args) { String str = "Hello World"; System.out.println(str.length()); System.out.println(str.charAt(1)); System.out.println(str.indexOf("h")); System.out.println(str.indexOf("o")); System.out.println(str.substring(4)); System.out.println(str.substring(4, str.length() - 2)); System.out.println(str.toLowerCase()); System.out.println(str.toUpperCase()); String[] split = str.split(" "); for (int i = 0; i < split.length; i++) { System.out.println(split[i]); } System.out.println("-----------------------------------"); String str1 = "Hello1 World2"; System.out.println(str1.indexOf("1", 4)); System.out.println(str1.lastIndexOf("l")); System.out.println(str1.lastIndexOf("l", 11)); System.out.println("-----------------------------------"); System.out.println("abc".compareTo("abcde")); System.out.println("abc".compareTo("abc")); System.out.println("12789".compareTo("123")); System.out.println("abc".equals("a")); System.out.println("abc".equals("abc")); System.out.println("abc".equalsIgnoreCase("ABC")); System.out.println("abc".concat("derfg")); System.out.println("nnnwa".replace("n", "g")); System.out.printf("浮点型变量的值为 " + "%f, 整型变量的值为 " + " %d, 字符串变量的值为 " + "is %s", 1.12f, 16, "LuckyNwa"); System.out.println("nwa".contains("nw")); System.out.println("nwa".endsWith("a")); System.out.println(" hello world ".trim());
} }
|
https://www.runoob.com/java/java-string.html 参考这
总结
length方法使用地方特别多,比如数组遍历时候就需要,字符串同,不知道长度可以直接用这方法获取
s=”aascsaxaca”;它的下标就是0到s.length()-1
indexOf可以用来查询是否存在,返回值为-1则不存在,也可以查询这个字符串第一次出现的地方
charAt方法可用于验证码的实现,把验证码需要的字符串存在一个变量里,通过charAt(new Random().nextInt(codeBox.length()))来获取随机字符
trim方法去首尾空格,用于登录时候输入有空格的把空格直接去掉,用的范围也挺广 以及split用的很多,可以根据空格,-等分割
isEmpty判断是否为空
StringBuffer 和 StringBuilder
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象
StringBuilder 类在 Java 5 中被提出,StringBuilder不是线程安全,StringBuffer 线程安全
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Demo1 { public static void main(String[] args) { StringBuilder sb; sb = new StringBuilder(10); sb.append("Runoob.."); System.out.println(sb); sb.append("!"); System.out.println(sb); sb.insert(8, "Java"); System.out.println(sb); sb.delete(5, 8); System.out.println(sb); StringBuilder luckyNwa = new StringBuilder("LuckyNwa"); luckyNwa.append("你好啊"); System.out.println(luckyNwa); } }
|

其他
转义序列
前面有反斜杠(\)的字符代表转义字符,它对编译器来说是有特殊含义的
列表展示了Java的转义序列:
