Java知识复习三
相关导航
Java剑开天门(一)
Java剑开天门(二)
Java剑开天门(三)
Java剑开天门(四)
Java剑开天门(五)
前言
本博文重在夯实Java基础的知识点,回归书本,夯实基础,学深学精
近期需要巩固项目和找实习,计划打算将Java基础从头复习一遍,夯实基础,可能对Java的一些机制不了解或者一知半解,正好借此机会深入学习,也算记录自己的一个学习总结。
Java基础参考书籍:《Java 开发实战经典 名师讲坛 第2版》与《Java核心技术 卷I》
一、Java常用类及方法
1、String类
1.1 length()
public int length();返回字符串长度
1.2 split()
public String[] split(String str):根据str做拆分
将一个字符串分割为子字符串,然后将结果作为字符串数组返回。
基本格式 :str1.split("符号",limit)
___________________________________________
(1)str1
必选项。要被分解的对象,即你想要进行操作的字符串,该对象不会被split方法修改。
(2)符号
可选项。以此符号为标志对字符串进行分割。如果忽略该选项,返回包含整个字符串的单一元素数组。
(3)limit
可选项。该值用来限制返回数组中的元素个数(也就是最多分割成几个数组元素,只有为正数时有影响)
注意split 方法的结果是一个字符串数组,在 str1 中每个出现 符号 的位置都要进行分解。这个符号不作为任何数组元素的部分返回。
___________________________________________
按照多个条件进行分割,所以需要使用“|”作为连字符
public class Hello_Java {
public static void main(String[] args) {
String test="no pains,no gains!";
String []a=test.split(" |,|!"); //这样" "和","和"!"都将成为分隔符,另外注意这一步相当于直接对数组a进行了赋值
System.out.println("分解后的单词个数为:"+a.length);
for(int i=0;i<a.length;i++)
{
System.out.println(a[i]);
}
}
}
___________________________________________
分割符可以用正则表达式来表示
@Test
public void splitDemo2(){
String str= "a33b444c555d";
//正则表达式中\d+表示一个或多个数字,java中\\表示一个普通\
//String[] split = str.split(Pattern.compile("\\d+").toString());
//两种写法都是一样的,下面写法简洁
String[] split = str.split("\\d+");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
}
1.3 charAt()
public cahr charAt(int index);根据下表获取字符串
1.4 contains()
public boolean contains(String str);判断当前字符串是否包含所给字符
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
String content="java是世界上最好的编程语言";
String flag="中华人民共和国万岁,人民万岁";
System.out.println(content.length());
System.out.println(flag.length());
System.out.println(content.charAt(0));
System.out.println(content.charAt(content.length()-1));
System.out.println(content.contains("java"));
System.out.println(content.contains("php"));
}
}
1.5 toCharArray()
public char[] toCharArray():将字符串转成字符数组
1.6 indexOf()
public int indexOf(String str):查找str首次出现的下标,存在则返回改下标,不存在则返回-1
1.7 lastIndexOf()
public int lastIndexOf(String str):查找字符串在当前字符串中最后一次出现的下标索引
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) {
String content="java是世界上最好的java语言,java真香";
//字符串方法的使用
//toCharArray():返回字符串对应的数组
//indexOf():返回字符串首次出现的位置
//lastIndexOf():返回字符串最后一次出现的位置
// System.out.println(content.toCharArray());
System.out.println(Arrays.toString(content.toCharArray()));
System.out.println(content.indexOf("java"));
//从字符串的索引等于4的位置开始,返回"java"出现的位置
System.out.println(content.indexOf("java",4));
System.out.println(content.lastIndexOf("java"));
}
}
1.8 trim()
public String trim():去掉字符串前后的空格
1.9 toUpperCase()
public String toUpperCase():将小写转成大写
1.10 endWith()
public boolean endWith(String str):判断字符串是否以str结尾
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
//trim():去掉字符串前后的空格
//toUpperCase():将小写转成大写
//endWith(String str):判断字符串是否以str结尾
//startWith(String str):判断是否以str结尾
String content1 = " hello world ";
String content2 =content1.trim();
System.out.println(content1);
System.out.println(content2);
System.out.println(content1.toUpperCase());
System.out.println(content1);
System.out.println(content1.toLowerCase());
System.out.println(content1);
String filename = "hello.java";
System.out.println(filename.endsWith(".java"));
System.out.println(filename.startsWith("hel"));
}
}
1.11 replace()
public String replace(char oldChar,char newChar):将旧字符串替换成新字符串
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
//replace(char oldChar,char newChar):将旧字符串替换成新字符串
//split(String str):根据str做拆分
String content="java是世界上最好的java编程语言,java真香";
System.out.println(content.replace("java","php"));
String say="java is the best programming language,java xiang";
String[] arr=say.split("[ ,]+");//使用空格和逗号拆分
// ,后加+表示"空格"或者","可以连续出现多个
System.out.println(arr.length);
for (String s:arr
) {
System.out.println(s);
}
}
}
- 补充
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
//补充
String s1="hello";
String s2="HELLO";
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));//忽略大小写的比较
//长度一样比ASCII码,长度不一样比长度
String s3="abc";//a:97;
String s4="xyz";//x:120;
System.out.println(s3.compareTo(s4));
String s5="abc";
String s6="abcxyz";
System.out.println(s5.compareTo(s6));
}
}
1.12 StringBuffer和StringBuilder
- StringBuffer:
可变长字符串
,JDK1.0提供,运行效率慢
,线程安全
- StringBuilder:
可变长字符串
,JDK1.5提供,运行效率
快,线程不安全
- 示例代码
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
//StringBuffer和StringBuilder
StringBuffer sb=new StringBuffer();//换成StringBuilder也一样
//append();追加
sb.append("java世界第一");
System.out.println(sb.toString());
sb.append("java真香");
System.out.println(sb.toString());
sb.append("java不错");
System.out.println(sb.toString());
//insert();添加
sb.insert(0,"我在前面");
System.out.println(sb.toString());
//replace();
sb.replace(0,4,"hello");
System.out.println(sb.toString());
//delete();删除
sb.delete(0,5);
System.out.println(sb.toString());
//delete();清空
sb.delete(0,sb.length());
System.out.println(sb.length());
}
}
2、Object类
Object类是所有类(包括超类,基类)的直接或间接父类,位于继承树的最顶层。任何类,如果没有书写extends显式地继承某个类,都默认直接继承Object类,否则为间接继承。它当中所定义的方法,是所有对象都具备的方法。Object类中可以存储任何对象,它作为参数时,可以接受任何对象;作为返回值时,可返回任何对象。
2.1 getClass()
getClass()方法会返回引用中存储的实际对象,通常用来判断两个引用中实际对象的类型是否一致。
public class test {
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name=name;
this.age=age;
}
}
public static void main(String[] args) {
Student stu1 = new Student("aaa", 20);
Student stu2 = new Student("bbb", 22);
//判断stu1和stu2是不是同一类型
Class class1 = stu1.getClass();
Class class2 = stu2.getClass();
if (class1 == class2) {
System.out.println("二者属于同一类型");
} else {
System.out.println("二者不是同一类型");
}
}
}
2.2 toString()
toString()方法会返回该对象的字符串表示,可以根据程序需求覆盖该方法,如:展示对象的各个属性的值
测试一:不重写Object类的toString()方法(Student类默认继承Object
)
package com.Sam;
public class test {
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name=name;
this.age=age;
}
}
public static void main(String[] args) {
Student stu1 = new Student("aaa", 20);
Student stu2 = new Student("bbb", 22);
System.out.println(stu1.toString());
System.out.println(stu2.toString());
}
}
输出
com.Sam.test$Student@1b6d3586
com.Sam.test$Student@4554617c
解释:Object类自身的toString()方法会返回一个字符串,即:
包名+类名+@+此对象哈希码的无符号十六进制表示
getClass().getName() + ‘@’ + Integer.toHexString(hashCode());菜鸡如我表示看不懂xd。
测试二:重写Object类的toString()方法
package com.Sam;
public class test {
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) {
Student stu1 = new Student("aaa", 20);
Student stu2 = new Student("bbb", 22);
System.out.println(stu1.toString());
System.out.println(stu2.toString());
}
}
输出
Student{name=‘aaa’,age=20}
Student{name='bbb’,age=22}
2.3 equals()
该方法默认实现为(this==obj)
,即比较两个对象地址
是否相同,也可重写,比较两个对象的内容是否相同。
==和equals方法之间的区别
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
输出
false
true
1)关系操作符“==”到底比较的是什么?
关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系
——《JAVA编程思想》
简单来说,==就是用来比较值是否相等
- 对于基本数据类型的变量,变量直接存储的是“值”,因此在用关系操作符==来进行比较时,比较的就是
“值” 本身
。 - 对于非基本数据类型的变量,即引用类型的变量。引用类型的变量存储的
并不是 “值”本身
,而是于其关联的对象
在内存
中的地址
。引用存放的是对象在堆中的地址
。
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=3;
int m=3;
System.out.println(n==m);
String str = new String("hello");
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1==str2);
str1 = str;
str2 = str;
System.out.println(str1==str2);
}
}
输出
true
fasle
true
2)equals方法比较的是什么?
在Object类中,equals方法是用来比较两个对象的引用
是否相等
,即是否指向同一个对象
。
-
如果
没有
对equals方法进行重写
,则比较的是引用类型的变量所指向的对象的地址
; -
诸如String、Date等类对equals方法进行了
重写
的话,比较的是所指向的对象的内容
。
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2));
}
}
输出
true
重写equals()方法
重写步骤
- 比较两个引用是否指向同一个对象
- 判断obj是否为null
- 判断两个引用指向的实际对象类型是否一致
- 强制类型转换
- 一次比较各个属性值是否相同
@Override
public boolean equals(Object obj) {
//1、判断两个对象是否为同一个引用
if (this==obj){
return true;
}
//2、判断obj是否为null
if (obj==null){
return false;
}
//3、判断是否为同一类型
// if (this.getClass()==obj.getClass())
if(obj instanceof Student){
//4、强制类型转换
Student s=(Student)obj;
if (this.name.equals(s.getName())&&this.age==s.getAge()){
return true;
}
}
return false;
}
package com.Sam;
public class test {
static class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object obj) {
//1、判断两个对象是否为同一个引用
if (this==obj){
return true;
}
//2、判断obj是否为null
if (obj==null){
return false;
}
//3、判断是否为同一类型
// if (this.getClass()==obj.getClass())
if(obj instanceof Student){
//4、强制类型转换
Student s=(Student)obj;
if (this.name.equals(s.getName())&&this.age==s.getAge()){
return true;
}
}
return false;
}
}
public static void main(String[] args) {
Student stu1 = new Student("aaa", 20);
Student stu2 = new Student("bbb", 22);
Student stu3=new Student("aaa",20);
Student stu4=stu1;
System.out.println(stu1.equals(stu2));
System.out.println(stu1.equals(stu3));
System.out.println(stu1.equals(stu4));
}
}
2.4 finalize()
- 当对象被判定为
垃圾对象
,由JVM自动调用此方法,用以标记垃圾对象
,进入回收队列
- 垃圾对象:没有有效引用指向此对象时,此对象为垃圾对象
- 垃圾回收:由gc销毁垃圾对象,释放数据存储空间
- 自动回收机制:JVM内存耗尽,
一次性回收
所有垃圾对象 - 手动回收机制:使用
System.gc()
,通知
JVM执行
垃圾回收
//finalize()方法重写
@Override
protected void finalize() throws Throwable {
System.out.println(this.name+"对象被回收了");
}
---------------------------------------------------------------
package com.Sam;
public class test {
static class Student{...}
public static void main(String[] args) {
//finalize()
//下面五种状态,并不会被回收
Student stu1=new Student("aaa",20);
Student stu2=new Student("bbb",20);
Student stu3=new Student("ccc",20);
Student stu4=new Student("ddd",20);
Student stu5=new Student("eee",20);
System.gc();
}
}
---------------------------------------------------------------
package com.Sam;
public class test {
static class Student{...}
public static void main(String[] args) {
//finalize()
new Student("aaa",20);
new Student("bbb",20);
new Student("ccc",20);
new Student("ddd",20);
new Student("eee",20);
System.gc();
}
}
输出
eee对象被回收了
ddd对象被回收了
ccc对象被回收了
bbb对象被回收了
aaa对象被回收了
3、包装类
基本数据类型 | 包装类型 |
---|---|
int | Integer |
char | Character |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
3.1 装箱
- 把
基本类型
转成引用类型
- 使用包装类的valueOf(值)方法
package com.Sam;
public class Demo01 {
public static void main(String[] args) {
//类型转换(装箱操作):把基本类型转成引用类型
//基本类型
int num1=18;
//使用Integer类创建对象
Integer integer1=new Integer(num1);
Integer integer2=Integer.valueOf(num1);
System.out.println(integer1);
System.out.println(integer1.getClass());
System.out.println(integer2);
System.out.println(integer2.getClass());
//类型转换(拆箱操作):把引用类型转成基本类型
Integer integer3=new Integer(100);
int num2=integer3.intValue();
System.out.println(num2);
//JDK1.5之后,提供自动装箱和拆箱的功能
int age=30;
//自动装箱
Integer integer4=age;
System.out.println(integer4.getClass());
//自动拆箱
int age2=integer4;
System.out.println(age2);
}
}
3.2 拆箱
- 把
引用类型
转成基本类型
- 使用xxxValue()方法
- 使用格式
xxx 变量名=包装类对象.xxxValue();
xxx代表基本数据类型
- 示例如上
3.3 valueOf()
- valueOf来将
基本类型
转换为包装类
- 使用格式
包装类名 对象名=包装类名.valueOf(对应的值);
3.4 parseXxx()
字符串
到对应的基本数据类型
- 包装类提供了一个功能,静态方法:parseXXX,该方法可以将
字符串
解析为对应的基本类型数据
,前提是该字符串能正确描述
要转换的基本类型
可以保存的值
- 使用格式
public class IntegerDemo2 {
public static void main(String[] args) {
String str = "123";
int a = Integer.parseInt(str);
double d = Double.parseDouble(str);
System.out.println(a); //123
System.out.println(d); //123.0
}
}
4、Scanner类
- Java 5添加了java.util.Scanner类,这是一个用于
扫描输入文本
的新的实用程序。 - 实例化代码
Scanner reader=new Scanner(System.in);
- 对象调用下列方法(函数),读取用户在命令行输入的各种数据类型
next.Byte()
nextDouble()
nextFloat
nextInt()
nextLine()
nextLong()
nextShot()
上述方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认。
nextLine()等待用户输入一个文本行
并且回车,该方法得到一个String
类型的数据。 - 常用API
delimiter() :返回此 Scanner 当前正在用于匹配分隔符的 Pattern
。
hasNext() :判断
扫描器中当前
扫描位置后
是否还存在下一段
。
hasNextLine() :如果在此扫描器的输入中存在另一行
,则返回true
。
next() :遇到第一个扫描有效字符,即第一个非空格非换行符
后面开始,一直获取到下一个空格,换行符之前
的,单个字符串
。【next()只读空格之前的数据,并且光标指向本行
】
nextLine() :可以扫描到一行内容
(当前行,光标所在行的内容,包括空格
、回车
)并作为一个字符串
而被获取到。读取输入后,nextLine()将光标定位在下一行
。
public class Text {
public static void main(String []args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个字符串(中间能加空格或符号)");
String a = input.nextLine();
System.out.println("请输入一个字符串(中间不能加空格或符号)");
String b = input.next();
System.out.println("请输入一个整数");
int c;
c = input.nextInt();
System.out.println("请输入一个double类型的小数");
double d = input.nextDouble();
System.out.println("请输入一个float类型的小数");
float f = input.nextFloat();
System.out.println("按顺序输出abcdf的值:");
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
System.out.println(f);
}
}
输出
请输入一个字符串(中间能加空格或符号)
我爱祖国!
请输入一个字符串(中间不能加空格或符号)
ILoveChina
请输入一个整数
520
请输入一个double类型的小数
12.26e3
请输入一个float类型的小数
3.1415926
按顺序输出abcdf的值:
我爱祖国!
ILoveChina
520
12260.0
3.1415925
public class inputInformation {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in); //构造Scanner类的对象scan,接收从控制台输入的信息
System.out.println("请输入你的姓名");
String name = scan.nextLine();//接收一个字符串,可以加除Enter以外的所有符号,包括空格和Tab
System.out.println("请输入你的ID");
String ID ;
while(scan.hasNextLine()) {// hasNextLine()方法判断当前是否有输入,当键盘有输入后执行循环
if(scan.hasNextInt()) {// 判断输入的值是否为整数类型,当为整数类型时执行循环
ID = scan.nextLine();
System.out.println("你输入的姓名为:"+name);
System.out.println("你输入的ID为:"+ID);
break;
}else {
System.out.println("请输入数字哦!");
ID = scan.nextLine();
continue;
}
}
}
}
输出
请输入你的姓名
西地那非
请输入你的ID
q764323221
请输入数字哦!
764323221
5、System类
System类,主要用于获取系统的属性和其他操作,构造方法是私有的
方法名 | 说明 |
---|---|
static void arraycopy(……) | 复制数组 |
static long currentTimeMillis() | 获取当前系统时间,返回的是毫秒值 |
static void gc() | 建议JVM赶快启动垃圾回收器回收垃圾 |
static void exit(int status) | 退出JVM,如果参数是0表示正常退出JVM,非0表示异常退出JVM |
System.out.println() | 换行输出 |
System.out.print() | 不换行输出 |
package com.Sam;
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) {
//arrcopy:数组复制
//src:源数组
//srcPos:从哪个位置开始复制
//destPos:目标数组的位置
//length:复制的长度
int[] arr={20,18,15,8,35,26,45,90};
int[] dest=new int[8];
System.arraycopy(arr,0,dest,0,arr.length);
for (int i = 0; i < dest.length; i++) {
System.out.println(dest[i]);
}
//Arrays.copyOf(original,newLength);
int[] arrr={1,2,3,4,5,6,7};
int[] arrrr= Arrays.copyOf(arrr,7);
for (int a:arrrr
) {
System.out.print(a);
}
System.out.println();
System.out.println(System.currentTimeMillis());//从1970年开始运行的毫秒数
long start=System.currentTimeMillis();
for (int i=0;i<99999999;i++){
for (int j=0;j<99999999;j++){
int result=i+j;
}
}
long end=System.currentTimeMillis();
System.out.println("用时:"+(end-start));
// System.gc();
System.exit(0);//退出JVM
System.out.println("程序结束了");//JVM退出,并没有打印这句话
}
}
输出
20
18
15
8
35
26
45
90
1234567
1627202421743
二、Lambda表达式
1、Lambda定义
- lambda表达式允许你通过表达式来代替功能接口。
- lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
- Lambda 表达式可以看作是一个
匿名函数
。
基本语法:
(parameters) -> expression 或 (parameters) ->{ statements; }
- paramaters
类似方法中的形参列表,这里的参数是函数式接口
里的参数
。这里的参数类型可以明确的声明, 也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。 - ->
可理解为“被用于”
的意思 - 方法体
可以是表达式
也可以代码块
,是函数式接口
里方法的实现
。代码块
可返回一个值
或者什么都不返回
,这里的代码块块等同于方法的方法体。如果是表达式
,也可以返回一个值
或者什么都不返回
。
// 1. 不需要参数,返回值为 2
() -> 2
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的和
(x, y) -> x + y
// 4. 接收2个int型整数,返回他们的乘积
(int x, int y) -> x * y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
2、函数式接口
- 一个接口有且只有一个抽象方法 。
- @FunctionalInterface注解
//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
void test(int a,int b);
}
//有返回值无参数
@FunctionalInterface interface NoParameterReturn {
int test();
}
//有返回值一个参数
@FunctionalInterface interface OneParameterReturn {
int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
int test(int a,int b);
}
———————————————————————————————
public class TestDemo {
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn = () -> {
System.out.println("无参数无返回值");
};
noParameterNoReturn.test();
OneParameterNoReturn oneParameterNoReturn = (int a) -> {
System.out.println("无参数一个返回值:" + a);
};
oneParameterNoReturn.test(10);
MoreParameterNoReturn moreParameterNoReturn = (int a, int b) -> {
System.out.println("无返回值多个参数:" + a + " " + b);
};
moreParameterNoReturn.test(20, 30);
NoParameterReturn noParameterReturn = () -> {
System.out.println("有返回值无参数!");
return 40;
};
//接收函数的返回值
int ret = noParameterReturn.test();
System.out.println(ret);
OneParameterReturn oneParameterReturn = (int a) -> {
System.out.println("有返回值有参数!");
return a;
};
ret = oneParameterReturn.test(50);
System.out.println(ret);
MoreParameterReturn moreParameterReturn = (int a, int b) -> {
System.out.println("有返回值多个参数!");
return a + b;
};
ret = moreParameterReturn.test(60, 70);
System.out.println(ret);
}
}
三、异常
1、异常概念
Java中错误分为
语法错误
和语义错误
。一个程序在编译
时没有错误
信息产生,但是在运行
时却有可能出现各种各样的错误
导致程序退出
,这类错误
统称为异常
。
一句话,异常就是
运行中产生的错误
。
异常
是导致程序中断运行
的一种指令流,如果不对异常进行正确的处理,可能导致程序的中断执行,造成不必要的损失。
故我们主要学习如何
正确处理异常的方法
。
在Java程序设计时,应充分地利用Java的
异常处理机制
,增进程序的稳定性
及效率
。
2、异常处理
2.1 异常类
在Java的异常结构中,有两个最常用的类,Exception类
和Error类
- Exception类
一般表示程序中出现的问题
,可以直接使用try……catch处理。
如算数异常、数字格式化异常都属于Exception的子类
。
Exception的子类有
1)NullPointerException,当您尝试使用指向
内存中空位置的引用
(null)时发生的异常
2)如果你想在代码里抛点什么,可以使用Throwable类或Exception类(和Exception类的后代)或者干脆自定义一个类来继承他们。
3)常用方法
①printStackTrace();打印异常信息
异常对象.printStackTrace();
②getStackTrace();返回一个表示该线程堆栈转储的堆栈跟踪元素数组
public StackTraceElement[] getStackTrace();
返回一个表示该[线程]堆栈转储的[堆栈跟踪元素数组]。
如果该线程尚未启动或已经终止,则该方法将返回一个零长度数组。
如果返回的数组不是零长度的,则其第一个元素代表[堆栈顶],它是[该序列中最新的方法调用]。
最后一个元素代表[堆栈底],是[该序列中最旧的方法调用]。
StackTraceElement[] stackTraceElements=异常对象.getStackTrace();
StackTraceElement有下面一些方法:
getFileName()
getClassName()
getMethodName()
getLineNumber()
③getMessage();是用来获取异常中的异常错误消息字符串
此方法不返回异常错误的类型,这是用来获得错误信息的一个函数。
e.toString()获取的信息包括异常类型和异常详细消息,而e.getMessage()只是获取了异常的详细消息字符串。
public String getMessage();
示例
String example=异常对象.getMessage();
- Error类
一般指的是JVM错误
,程序
中无法处理
。
2.2 try……catch处理格式
1)代码格式
try{
有可能出现异常的语句;
}catch(异常类 异常对象){
异常的处理语句;
}catch(异常类 异常对象){
异常的处理语句;
}
……
[finally]{
一定会运行到的程序代码
}//不管程序是否捕获到了异常,如果写了finally关键字代码块,程序一定会执行此代码块。
注意点
- finally是
可选
的。 - finally中声明的是
一定会被执行的代码
。即使catch又出现异常了
,try中有return语句,catch中有return语句等情况。 - 像
数据库连接
、输入输出流
、网络编程Socket
等资源,JVM是不能自动回收
的,我们需要自己手动的进行资源的释放。此时的资源释放
,就需要声明在finally中
。 - 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。
- 一旦try中的异常对象匹配到某一个catch时,就进入catch进行异常的处理。一旦完成处理,就跳出当前的try-catch结构(在没有写finally的情况),继续执行后面的代码。
- catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
- catch中的异常类型如果有子父类关系,则要求子类一定声明在父类的上面,否则报错。
- 常用的异常对象处理方法:①String getMessage() ②printStackTrace()。
- 在try结构中声明的
变量
,在出
了try结构以后,就不能再被调用
了。 - try-catch-finally结构可以互相嵌套。
2.3 throws和throw关键字处理格式
在异常处理中有两个非常相似的关键字,throws和throw这两个关键字。
用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常。
1) throws关键字
主要用于方法声明
上,指的是当方法之中出现异常
后交由被调用处
处理。
格式
修饰符 返回值类型 方法名(参数列表) throws 异常类(){
}
示例
class MyMath{
//由于存在throws,那么就表示此方法里面产生的异常交给被调用处处理
public static int div(int x, int y) throws Exception{
return x/y;
}
}
————————————————————————————————————————————————
//main函数抛出的异常由JVM(Java虚拟机)处理,也就是嵌套,最后交给JVM处理。
public class TestDemo{
public static void main(String args[]) throws Exception{
System.out.println(MyMath.div(10,2));
}
2) throw关键字
在程序之中可以直接使用throw手动抛出异常
类的实例化对象
。
格式
throw new Exception("自己定义的异常");
示例
public class TestDemo{
public static void main(String args[]){
try{
throw new Exception("自己定义的异常");
}catch(Exception e){
e.printStackTrace();
}
}
}
throw的意义——Java的所有异常都是使用throw关键字抛出的,只是这部分代码已经被Java隐藏起来了,开发者感觉不到而已。
3) Exception类和RuntimeException类
- Exception类在程序中
必须使用
try……catch进行处理; - RuntimeException是Exception的子类,其可以
不使用t
ry……catch代码块,但是如有异常产生,异常交给JVM
处理。但建议还是使用try……catch代码块处理异常。
常见的RuntimeException
①NumberFormatException
②ClassCastException
③NullPointerException
④ArrayIndexOutOfBoundsException
4) 自定义异常类
用户根据自己的需求定义自己的异常类
自定义异常类,只需要继承Exception类或者RuntimeException类
class 类名 extends 异常类{
}
与throws和throw使用
自定义异常类不会自动抛出异常?【对或者错】
package 异常处理;
public class People {
private int age;
private double salary;
private String name;
public void setAge(int age) throws NegtiveException {
if(age < 0){ //如果年龄小于0则抛出异常
throw new NegtiveException();
}
else {
this.age = age;
}
}
public void setSalary(double salary) throws NegtiveException {
if(salary < 0) //如果薪水小于0则抛出异常
{
throw new NegtiveException();//要有这个进行构造参数抛出异常
}
else {
this.salary = salary;
}
}
public void setName(String name) {
this.name = name;
}
public void showInfo() {
System.out.println("name:" + name +" " + "age:" + age + " "+"salary:" + salary);
}
}
5) 断言【assert】
断言
就是肯定
一个结果的返回值
是正确
的;
- Java在执行的时候默认是
不启动断言检查
的(这个时候,所有的断言语句都 将忽略!),如果要开启断言检查,则需要用开关-enableassertions
或-ea
来开启
。 - 格式
1)assert <boolean表达式>
如果<boolean表达式>为true,则程序继续执行。
如果为false,则程序抛出AssertionError,并终止执行。
2)assert <boolean表达式> : <错误信息表达式>
如果<boolean表达式>为true,则程序继续执行。
如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。
示例
public class AssertFoo {
public static void main(String args[]) {
//断言1结果为true,则继续往下执行
assert true;
System.out.println("断言1没有问题,Go!");
System.out.println("\n-----------------\n");
//断言2结果为false,程序终止
assert false : "断言失败,此表达式的信息将会在抛出异常的时候输出!";
System.out.println("断言2没有问题,Go!");
}
}
开启-ea开关输出
断言1没有问题,Go!
-----------------
Exception in thread "main" java.lang.AssertionError: 断言失败,此表达式的信息将
会在抛出异常的时候输出!
at AssertFoo.main(AssertFoo.java:10)
- 总结
assert既然是为了调试测试程序用,不在正式生产环境下用,那应该考虑更好的测试JUint来代替其做用,JUint
相对assert关键的所提供的功能是有过之而无不及。当然完全可以通过IDE debug来进行调试测试。
3、优雅写异常的一种方式
3.1 异常枚举类
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnum {
PRICE_CANNOT_BE_NULL(400, "价格不能为空"),
PARAM_CANNOT_BE_NULL(400, "参数不能为空"),
CATEGORY_NOT_FOUND(404, "商品分类没有找到"),
SPEC_GROUP_NOT_FOUND(404, "商品规格组没有查到"),
BRAND_SAVE_ERROR(500, "新增品牌失败"),
GOODS_SAVE_ERROR(500, "新增商品失败"),
BRAND_NOT_FOUND(404, "品牌没有找到"),
UPLOAD_FILE_ERROR(500, "文件上传失败"),
INVALID_FILE_TYPE(400, "无效文件类型"),
SPEC_PARAM_NOT_FOUND(404,"商品规格参数不存在"),
GOODS_NOT_FOUND(404,"商品不存在"),
SPU_DETAIL_NOT_FOUND(404, "商品详情不存在"),
GOODS_SKU_NOT_FOUND(404,"sku没有找到");
private int code;
private String msg;
}
3.2 异常结果集
// 自定义异常处理.vo
@Data
public class ExceptionResult {
private int status;
private String message;
private Long timestamp;
public ExceptionResult(ExceptionEnum exceptionEnum) {
this.status = exceptionEnum.getCode();
this.message = exceptionEnum.getMsg();
this.timestamp = System.currentTimeMillis();
}
}
3.3 自定义异常
// 自定义异常
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class CarryExcepttion extends RuntimeException {
private ExceptionEnum exceptionEnum;
}
// 测试
// throw new CarryExcepttion(ExceptionEnum.BRAND_NOT_FOUND);
示例
@Getter
public class SellException extends RuntimeException {
private Integer code;
public SellException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
//public RuntimeException(String message)
//用指定的详细信息构造一个新的运行时异常。
//参数 message 的详细信息保存为以后的 Throwable.getMessage()方法检索。
----
//此示例中没有对message赋值,而是根据运行是异常信息来进行写入
//
this.code = resultEnum.getCode();
}
public SellException(Integer code, String message) {
super(message);
this.code = code;
}
}
// 测试
// throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
3.4 主方法main和其它方法抛出异常
class example{
public static void main(String[] args) throws Exception{//认为固定写法
demo();
}
public void demo throws CarryExcepttion {
if(表达式){
throw new CarryException(实参列表);【重点】
}
}
}
四、包
包的主要目的是实现程序的分割保存
。
1、包的基本概念
包(package)
是在使用多个类或者接口时,为了避免名称重复
和程序分割保存
而采用的一种措施。
- 格式
package 包名称.子包名称; //最右边的包名称就是这个类所在的包;
- import导包
类的导入
import 包名称.子包名称.类名称;//手动导入所需要的类;
import 包名称.子包名称.*;//由JVM自动加载所需要的类;
-------------
这两种的导入性能是一样的,使用*导入也是自动加载所需要的类,
而不需要的类根本不会被加载进来。
-------------
如果一个程序同时导入了两个包的同名类,
在使用时就要明确地写出完整的【包名称.子包名称.类名称】以做区分。
- 系统常见包
包名称 | 说明 |
---|---|
java.lang | 基本包,现可以自动导入 |
java.lang.reflect | 反射机制的包,是java.lang的子包 |
java.util | 工具包,常用类库、日期操作 |
java.text | 文本处理类库 |
java.sql | 数据库操作包 |
java.io | 输入输出处理 |
java.net | 网络编程包 |
java.awt | 构成抽象窗口工具集的多个类,被用来构建和管理应用程序的图形用户界面(GUI) |
java.swing | 建立图形界面所需的包,相对于java.awt包而言是轻量级组件 |
2、JAR包和WAR包
2.1 JAR包
一般情况下降*.class文件压缩成一个文件交付给客户使用,那么这样的文件就被称为JAR包(Java Archive File)
- 命令
jar [jar-文件] [manifest-文件] [-C 目录] 文件名 文件名 ……
2.2 WAR包
- WAR包时一个可以·直接运行的Web模块·,通常用于网站,打成包
部署
到容器中。以Tomcat为例来说,将war包部署在其/webApps/目录下,然后启动tomcat,这个包就会自动解压,就相当于发布了。 - WAR包时sun提出的一种Web应用程序格式,与JAR包类似,是
很多文件的压缩包
。 - 简单来说,WAR包是Java Web程序打的包,WAR包里边含有写好的代码编译成的class文件、依赖的包、配置文件、所有的网站页面、包括html等等。一个
WAR包
可以理解为是一个Web项目
,里面是项目的所有东西。 - 区别
JAR
文件的目的是把类和相关的资源
封装到压缩的归档文件中。而对于WAR
文件来说,一个WAR文件代表一个Web应用程序
,它可以包含servlet、html页面、Java类、图像文件以及组成Web应用程序的其他资源,而不仅仅是类的归档文件。
3、服务器运行JAR和WAR
- 通过
JAR
运行实际上是启动了内置的tomcat
,所以用的是应用的配置文件中的端口
- 通过
WAR
直接部署到tomcat之后,内置的tomcat就不会启用
,所以相关配置
就以安装的tomcat为准
,与应用的配置文件就没有关系了 - 运行格式
java -jar 【jar包名称】
导出能够正常进行部署的war包了,将此包放到tomcat的webapps目录下就可以正常启动了。
//需要用系统的tomcat
4、命名规范
- 类 所有单词的首字母大写,如TestJava;
- 方法 第一个单词的首字母小写,之后的每个单词的首字母大写,如getInfo();
- 属性 第一个单词的首字母小写,之后的每个单词的首字母大写,如studentName();
- 包 所有单词的字母小写,如org.yxy.demo;
- 常量 所有单词的字母大写,如FLAG。