Java剑开天门(三)

Java知识复习三


相关导航
Java剑开天门(一)
Java剑开天门(二)
Java剑开天门(三)
Java剑开天门(四)
Java剑开天门(五)



前言

本博文重在夯实Java基础的知识点,回归书本,夯实基础,学深学精

近期需要巩固项目和找实习,计划打算将Java基础从头复习一遍,夯实基础,可能对Java的一些机制不了解或者一知半解,正好借此机会深入学习,也算记录自己的一个学习总结。
Java基础参考书籍:《Java 开发实战经典 名师讲坛 第2版》与《Java核心技术 卷I》


一、Java常用类及方法

Java常用类
String类
Object类
包装类
Scanner类
System类
length方法
split方法
charAt方法
contains方法
toCharArray方法
indexOf方法
lastIndexOf方法
trim方法
toUpperCase方法
endWith方法
replace方法
StringBuffer和StringBuilder
getClass方法
toString方法
equals方法
finalize方法
arraycopy方法
currentTimeMillis方法
gc方法
exit方法
装箱
拆箱
valueOf方法
parseXXX方法
next方法
nextLine方法
nextXxx方法

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、包装类

基本数据类型包装类型
intInteger
charCharacter
byteByte
shortShort
longLong
floatFloat
doubleDouble
booleanBoolean

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的子类,其可以不使用try……catch代码块,但是如有异常产生,异常交给JVM处理。但建议还是使用try……catch代码块处理异常。
    常见的RuntimeException
    ①NumberFormatException
    ②ClassCastException
    ③NullPointerException
    ④ArrayIndexOutOfBoundsException
4) 自定义异常类

 用户根据自己的需求定义自己的异常类
 自定义异常类,只需要继承Exception类或者RuntimeException类

class 类名 extends 异常类{

}throwsthrow使用
自定义异常类不会自动抛出异常?【对或者错】
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。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值