Java基础笔记

本文详细探讨了Java的优势(简单性、安全性、可移植性等)、注释类型、标识符与关键字、数据类型(包括基本类型和引用类型)、强弱类型、进制表示、浮点数扩展、布尔类型、Unicode编码、类型转换、常量与变量规范、逻辑运算符和三元逻辑运算、Scanner用法、循环结构实例、面向对象概念、类与对象创建、构造器与内存分析、封装与继承、多态、静态与抽象类、接口与内部类、异常处理和自定义异常。
摘要由CSDN通过智能技术生成

JAVA笔记

Java的优势和特性是什么?

1、Java的优势和特性是什么?
Java的话具有简单性、安全性、可移植性、面向对象、多线程、健壮性、分布式

在Java中注释有哪几种?

2、在Java中注释有哪几种?
有三种 分别是 单行注释 多行注释 和文本注释

Java中的标识符和关键字是什么?

3、Java中的标识符和关键字是什么?
标识符就是指类名、变量名、方法名都是标识符
关键字就是 如:static public abstract if extend implement 等

Java的数据类型有哪些?

4、Java的数据类型有哪些?
Java一共有八大数据类型

byte(字符型)
short(短整型)
int(整型)
long(长整型)

float(浮点型)
double(长浮点型)

char(字符型)
所有的引用类型

什么是强类型语言?

5、什么是强类型语言?
指一个变量一旦被赋予数据类型,如果不强制转换数据类型,那么这个变量将永久是这种数据类型

什么是弱类型语言?

6、 什么是弱类型语言?
指一个变量会随机应变来根据所需而转换自己的类型

在Java中各种进制的数怎么表示

7、在Java中各种进制的数怎么表示
如:
10进制:10
2进制:0b
8进制: 0
16进制:0x

浮点数怎么扩展?银行的业务怎么表示?

8、浮点数怎么扩展?银行的业务怎么表示?
浮点类型就好比

float a = 0.1f;
float b = 0.1f;
system.out.print(a == b);

这个的输出就是true
但是

float a = 0.1f;
double b = 0.1;
system.out.print(a == b);

的结果就是false

第一个是true是因为a和b在内存中指向的是同一块地址。“==”则比较的是两者的内存地址是否相同
第二个是false是因为一个是以float开辟的数据 一个是以double开辟的数据,所以两者的地址不同,导致比较为false

布尔类型怎么扩展?

9、布尔类型怎么扩展?
比如

Boolean flag =falseif(flag){
return 0;
}
if(flag == true){
return 0;
}

两种方法都可以但是第一种显得要更好一点,更专业一点

引用类型怎么拓展

10. 引用类型怎么拓展
比如

String s1 = new String("adc");
String s2 = new String("adc");
system.out.print(s1 == s2);

这时候输出的结果就是false,理由和上上一个是一样的,new 直接开辟了一个新得内存地址,导致了s1和s2不相同

但是这种情况下就是一模一样了

String s1 = “abc”
String s2 = “abc”
system.out.print(s1 == s2);

这样得出得结果就是true

Unicode编码得范围?

11. Unicode编码得范围?
是从u0000~uFFFF
例子就比如

char s3 = '\u0061';
输出得结果就是字母a

转译字符

12. 转译字符
如:“\t"------- 插入一个table制表符
”\r"------换行

类型转换

13. 类型转换
从高到低转换需要强制转换
但是从低到高则不需要强制转换
而各个转换得级别如下由低到高:
数值型数据的转换:byte→short→int→long→float→double。
字符型转换为整型:char→int。

Java中的常量和变量怎么规定与规范?

14. Java中的常量和变量怎么规定与规范?
常量不同于c中的常量定义
在Java中常量可以直接在类里面用 final 和 static来修饰

class Test(){
 final static double PI = 3.1415926;
}

这样来定义
而变量 则和c的差不多
就比如

class Test1(int i){
	i+=1;
	retrun 0;
}

这里面的i就是局部变量

而其命名规范则如下:
类名:首字母大写+驼峰
常量:字母大写+驼峰 MAX_VALUE
局部变量:首字母小写+驼峰
方法:首字母小写+驼峰:run(),runRun()
类成员变量:首字母小写+驼峰

逻辑运算符的左移<< 和右移 >>该如何使用?

15. 逻辑运算符的左移<< 和右移 >>该如何使用?
首先这个是直接与计算机打交道,所以在算法中有着非常高的效率
其次如2*8在Java中经常会使用2<<3来解决
因为二进制
0000 0000 —0
0000 0001 —1
0000 0010 —2
0000 0011----3
0000 0100----4
0000 1000----8
0001 0000 ----16
所以在Java中左移一个单位就是乘以2
右移一个单位就是初一2

三元逻辑运算是怎么进行的?

16. 三元逻辑运算是怎么进行的?
在Java中存在着这样的一种运算三元运算 x ?y : z
这种运算的原理就是如果x为true则执行y 如果为false则执行z
这种运算的好处是相对于if判断来说更加方便
例如: int result = time < 10 ? '0' + time : time;

生成JavaDoc文档:

17. 生成JavaDoc文档:
选择你需要生成文档的目录后打开cmd,然后输入javadoc -encoding UTF-8 -charset UTF-8 需要文档化的目标文件‘
idea生成JavaDoc文档则只需要编写注释文档后在tools里点击即可

scanner该怎么用?使用后该注意什么

18. scanner该怎么用?使用后该注意什么?
scanner是一个对象,而要向Java输入一个字符&数字,就需要new 出一个Scanner对象
具体方法如下:

 Scanner scanner = new Scanner(System.in);
        if(scanner.hasNext()){
            String str = scanner.next();
            System.out.println(str);
        }

但是其本质还是I/O流所以在不结束之前会一直占用资源,所以需要在最后写上
scanner.close();来结束输入流

 Scanner scanner = new Scanner(System.in);
        if(scanner.hasNext()){
            String str = scanner.next();
            System.out.println(str);
        }
  scanner.close();

注:其中scanner后面有时候会跟着next()和nextLine()这两个方法的本质区别是前者遇到空格就会把空格当成截断符或结束符。所以在空格后面的字母就无法输入,比如Hello World用next()的话World就不会被打印出来,但是用nextLine的话则是以回车键为结束符,所以Hello World会完整的输出

如何使用for循环打印出99表?

19.如何使用for循环打印出99表?

public class Test {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int i1 = i; i1 >0;i1--) {
                int sum = i* i1;
                System.out.print(i+"*"+i1+"="+sum+"\t");
            }
            System.out.println();
        }
    }
}

结果
11=1
2
2=4 21=2
3
3=9 32=6 31=3
44=16 43=12 42=8 41=4
55=25 54=20 53=15 52=10 51=5
6
6=36 65=30 64=24 63=18 62=12 61=6
7
7=49 76=42 75=35 74=28 73=21 72=14 71=7
88=64 87=56 86=48 85=40 84=32 83=24 82=16 81=8
99=81 98=72 97=63 96=54 95=45 94=36 93=27 92=18 9*1=9
或者

public class Test {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int i1 = 1; i1 <=i;i1++) {
                System.out.print(i+"*"+i1+"="+(i* i1)+"\t");
            }
            System.out.println();
        }
    }
}

1*1=1	
2*1=2	2*2=4	
3*1=3	3*2=6	3*3=9	
4*1=4	4*2=8	4*3=12	4*4=16	
5*1=5	5*2=10	5*3=15	5*4=20	5*5=25	
6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36	
7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49	
8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64	
9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81	

如何利用for来输出一个5行的三角形?

20. 如何利用for来输出一个5行的三角形?
思路L:主要是考虑拼接法,这个三角形可以由半个的倒三角
和一个三角组成

public class Test {
    public static void main(String[] args) {
        for (int i = 1; i <=5; i++) {
            for (int i1 = i; i1 <=5; i1++) {
                System.out.print(" ");
            }

            for (int i2 = 1; i2 <=i;i2++){
                System.out.print("^");
            }

            for (int i3 = 1; i3 <i;i3++){
                System.out.print("^");
            }
            System.out.println();
        }

    }
}

     ^
    ^^^
   ^^^^^
  ^^^^^^^
 ^^^^^^^^^

Java中什么是方法?方法怎么定义?

21. Java中什么是方法?方法怎么定义?
在Java中方法一般是指一些语句的有序集合,并可以被调用来解决问题。
方法的设计最好是一个方法一个坑,一个方法去完成一个功能,而不应该在一个方法中有解决多个功能的语句。

在Java中方法一般是 由 修饰符 引用类型 方法名(参数类型 参数){方法体}
例如:

public class Test {
    public static void main(String[] args) {
        int a = 1 ,b = 2;
        System.out.println(max(a,b));
    }

    public static int max(int num1,int num2){
        int value = num1 > num2 ? num1:num2;
        return value;
    }
}

什么是值传递?什么是引用传递?

22. 什么是值传递?什么是引用传递?
值传递在Java中本质意义就是 = 赋值,比如 int a = 0,int b;
此时将 b = a ;这样a的值就赋给了b,在内存中开辟出一块空间用来存放a,a的值是0,在赋值后让b指向了存储着0的地址。这就是值传递。在Java中一般都是值传递。

引用传递更多的用于c中,比如a的地址是x0235 ,然后创建指针p指向这地址,然后再通过指针找到地址更改里面的值,这样就是引用传递。

但是在Java中引用传递更直接的表示就是创建对象后,对对象的属性赋值。

方法的重载和重写

23. 方法的重载和重写
在Java中重载的要求是:
方法名必须相同, 引用类型不相同,参数类型不相同,参数个数不相同
重写的要求则是:
方法名必须相同,引用类型相同,参数类型相同,参数个数相同,方法体不相同,但是重写是用在继承的时候,即子类继承父类获得父类的方法,并在子类中重写

class A{
    public void run(){};
}

class B extends A{
    @Override
    public void run() {
        System.out.println("A Override");
    }
}

Java中的可变参数怎么用?

24. Java中的可变参数怎么用?
在Java中当你设置了一个方法后需要设置参数,但是你并不确定别人给你传了多少个参数,这时候你就可以用可变参数来解决这个问题。
就如:

public class Math1 {
    public int max(int... num){
        if(num.length == 0){
            System.out.println("error");
        }
        int result = num[0];
        for (int i = 0; i <num.length ; i++) {
            if(result<num[i]){
                 result =num[i];
            }
        }
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        int a = 55 ,b = 2,c = 55641, d = 4444, e = 44441545;
        Math1 math1 = new Math1();
        System.out.println(math1.max(a,b,c,d,e));
    }

}

在Java中如何计算出5的阶乘?

25. 在Java中如何计算出5的阶乘?
可以设计出一个方法并使用递归来进行
如下:

public class Test {
    public static void main(String[] args) {
        System.out.println(aug(5));
    }

    public static  int aug(int num){
        if(num == 1){
         return 1;
        }
        return num*aug(num-1);
    }
}

在Java中数组的创建是如何在栈和堆中体现的?

26. 在Java中数组的创建是如何在栈和堆中体现的?
在Java中 数组一般可以通过动态和静态创建。
动态创建就是先在栈中声明后,再通过new出一个对象然后在堆中开辟出一块连续的数据类型相同的空间。

静态创建则是通过直接赋值的方法来创建一个数组

在使用数组的时候有什么需要注意的?

27. 在使用数组的时候有什么需要注意的?
首先,数组一旦创建就不可更改,如果需要更改长度则需要另外再创建一个数组。其次,数组在创建时的数据类型决定了其内容的数据类型,如果数组的类型与其元素的数据类型不相同则会报错,最后还要注意在取数组元素的时候要取0-数组.lenth-1,因为数组的长度是length但是数组的下标是从0开始的所以得-1,不然会报数组下标越界的错误。数组也是对象,其数组的元素可以相当于对象的成员变量。

Java使用for:each 遍历数组和for遍历数组有什么区别?

28. Java使用for:each 遍历数组和for遍历数组有什么区别?
首先for:each的用法是for用法的进阶版本,这个方法是省略了数组的下标,能更方便的输出一个数组的元素,但是相较于for 的用法来说除了能更方便的输出外,并不能更好的操作数组中的元素。

假设有一个长度为5的数组,写一个算法来反转数组

29. 假设有一个长度为5的数组,写一个算法来反转数组。
分析:这道题只要想到用第二个数组来接收题目数组的数据就可以了。首先可以再创建一个题目数组大小的数组,并把题目数组的末元素赋值给新数组的首位即可完成
代码:

public class Test {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5};
        printArrays(a);
        System.out.println();
        change(a);
    }

    public static void change(int[] a){
        int[] b = new int[a.length];
        if(a.length==0){
            System.out.println("数据异常");
        }else{
            for (int i = 0,i1 = a.length-1; i <a.length ; i++,i1--) {
                    b[i1] = a[i];
                }
            }
            printArrays(b);
        }

    public static void printArrays(int[] a){
        for (int num:a) {
            System.out.print(num+"\t");
        }
    }

}
1	2	3	4	5	
5	4	3	2	1

二维数组如何定义?

30.二维数组如何定义?

public class Test {
    public static void main(String[] args) {
        int[][] a = new int[4][4];

        for (int i = 0; i <a.length ; i++) {
            for (int j = 0; j <a.length ; j++) {
                a[i][j] = 2;
            }
        }

        for (int i = 0; i <a.length ; i++) {
            for (int j = 0; j <a.length ; j++) {
                System.out.print(a[i][j]+"\t");
            }
            System.out.println();
        }
    }
}

Arrays类的使用

31. Arrays类的使用
用法如下:

public class Test {
    public static void main(String[] args) {
        int[] a = new int[6];
        Arrays.fill(a,2,5,2);
        System.out.println(Arrays.toString(a));

    }
  }

值得注意的一点是,当你使用Arrays.toString的时候
请使用 System.out.println,不然会像我这样忘记了然后找了半天错误

Java中的冒泡排序

32. Java中的冒泡排序
使用Arrays中的sort方法和自己写的冒泡排序方法:

public class Test {
    public static void main(String[] args) {
        int[] a ={5,7,6,9,1,4};
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        System.out.println();
        sortArrays(a);
        System.out.println(Arrays.toString(a));
    }

    public static void sortArrays(int[] a){
        int b =0;
        boolean c=false;
        if(a.length == 0){
            System.out.println("数据异常");
        }else{
            for (int i = 0; i < a.length; i++) {
                if(a[i]>a[++i]){
                    b=a[++i];
                    a[++i]=a[i];
                    a[i]=b;
                }
                c = true;
            }
        }
        if(!c){
            System.out.println("已完成排序");
        }
    }
}

[1, 4, 5, 6, 7, 9]

[1, 4, 5, 6, 7, 9]

给定一个1111的矩阵,在2,3处有值2,在8,4处有值4,用Java实现其压缩矩阵,并还原

33. 给定一个11*11的矩阵,在2,3处有值2,在8,4处有值4,用Java实现其压缩矩阵,并还原

public class Test {
    public static void main(String[] args) {
        //有一个11*11的数组,使其转换成稀疏矩阵中后再,解压缩回来

        int[][] arrays1 = new int[11][11];
        arrays1[2][3] = 2;
        arrays1[8][4] = 4;

        //打印出原始数组
        for (int[] ints : arrays1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        //计算出原始数组中有效元素的个数
        int flag = 0;
        for (int i = 0; i < arrays1.length; i++) {
            for (int j = 0; j < arrays1[i].length; j++) {
                if(arrays1[i][j] != 0){
                    flag++;
                }
            }
        }
        //创建稀疏数组
        int[][] arrays2 = new int[flag+1][3];
        arrays2[0][0] = 11;
        arrays2[0][1] = 11;
        arrays2[0][2] = flag;

        //遍历原数组,找到有效元素的位置并放入稀疏数组中
        int count = 0;
        for (int i = 0; i < arrays1.length; i++) {
            for (int j = 0; j < arrays1[i].length; j++) {
                if(arrays1[i][j] != 0){
                     count++;
                     arrays2[count][0]=i;
                     arrays2[count][1]=j;
                     arrays2[count][2]=arrays1[i][j];
                }
            }
        }
        //遍历稀疏矩阵
        for (int[] ints : arrays2) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }

        //解压缩稀疏矩阵
        //遍历稀疏矩阵然后创建解压缩数组
        int[][] arrays3 = new int[arrays2[0][0]][arrays2[0][1]];
        for (int i = 1; i <arrays2.length ; i++) {
            for (int j = 0; j <arrays2[i].length; j++) {
                arrays3[arrays2[i][0]][arrays2[i][1]] = arrays2[i][2];
            }
        }


        //输出还原数组
        for (int[] ints : arrays3) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }
}

0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	4	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
11	11	2	
2	3	2	
8	4	4	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	2	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	4	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0	
0	0	0	0	0	0	0	0	0	0	0

当编写了工具类后代码就急剧缩减

当编写了工具类后代码就急剧缩减

public class Test {
    public static void main(String[] args) {
        //有一个11*11的数组,使其转换成稀疏矩阵中后再,解压缩回来
        int[][] arrays1 = new int[11][11];
        arrays1[2][3] = 2;
        arrays1[8][4] = 4;
        //打印出原始数组
        for (int[] ints : arrays1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        Tootls tootls = new Tootls();
        //创建稀疏矩阵
        int[][] arrays2 = tootls.createSparseArrays(arrays1);
        //解压缩稀疏矩阵
        tootls.returnSparseArrays(arrays2);
    }
}

工具类中的创建稀疏矩阵:

    //创建稀疏矩阵
    public int[][] createSparseArrays(int[][] arrays1){
        //计算出原始数组中有效元素的个数
        int flag = 0;
        for (int i = 0; i < arrays1.length; i++) {
            for (int j = 0; j < arrays1[i].length; j++) {
                if(arrays1[i][j] != 0){
                    flag++;
                }
            }
        }
        //创建稀疏数组
        int[][] arrays2 = new int[flag+1][3];
        arrays2[0][0] = arrays1.length;
        arrays2[0][1] = arrays1.length;
        arrays2[0][2] = flag;

        //遍历原数组,找到有效元素的位置并放入稀疏数组中
        int count = 0;
        for (int i = 0; i < arrays1.length; i++) {
            for (int j = 0; j < arrays1[i].length; j++) {
                if(arrays1[i][j] != 0){
                    count++;
                    arrays2[count][0]=i;
                    arrays2[count][1]=j;
                    arrays2[count][2]=arrays1[i][j];
                }
            }
        }
        //遍历稀疏矩阵
        for (int[] ints : arrays2) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        return arrays2;
    }

工具类中的解压缩稀疏矩阵:

//解压缩稀疏矩阵
    public void returnSparseArrays(int[][] arrays2){
        //遍历稀疏矩阵然后创建解压缩数组
        int[][] arrays3 = new int[arrays2[0][0]][arrays2[0][1]];
        for (int i = 1; i <arrays2.length ; i++) {
            for (int j = 0; j <arrays2[i].length; j++) {
                arrays3[arrays2[i][0]][arrays2[i][1]] = arrays2[i][2];
            }
        }


        //输出还原数组
        for (int[] ints : arrays3) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }

什么是面向对象?

34. 什么是面向对象?
在Java中面向对象可以看成是把一项复杂的项目,而需要思考该项目要需要由哪几部分构成,进而分工成很多的小项目,而每一个小项目又可以分成更小的项目。总而言之,面向对象是需要多人协调进行的。更通俗的来说,面向对象就是把复杂问题抽象化,而抽象化后问题又变得简单化,转而通过封装,继承,实现把所有问题都容纳到一个类里面去。

类和对象该如何创建?

35. 类和对象该如何创建?
在Java中要构成一个类,其所需的元素的个数为二,二分别是属性和方法。一个功能再强大的类也不会脱离这个构成的要素。
举个例子:定一个猫类,猫的属性是:猫有名字,猫有年龄,再定义一个猫的方法,猫会抓老鼠

猫类:

public class Cat {
    String catName;
    Integer catAge;

    public String getCatName() {
        return catName;
    }

    public void setCatName(String catName) {
        this.catName = catName;
    }

    public Integer getCatAge() {
        return catAge;
    }

    public void setCatAge(Integer catAge) {
        this.catAge = catAge;
    }


    public void catCatchMonth(){
        System.out.println("The cat are catching month now!");
    }
}

调用,并创建猫对象

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.setCatAge(123);
        cat.setCatName("凯路");
        System.out.println(cat.catName+"\t"+cat.catAge);
        cat.catCatchMonth();
    }
}

Java中的构造器怎么定义得?有什么用?当使用了有参构造器后该注意些什么?

36. Java中的构造器怎么定义得?有什么用?当使用了有参构造器后该注意些什么?
构造器得定义方法和普通的方法没有太大区别。主要就是不能有返回类型,且构造器必须和类名相同

Java中当你初始化一个对象,也就是 new出一个对象后,明明什么属性都没有为什么还会有输出?那是因为当你创建一个类后,会生成一个隐形的无参构造器。
而构造器的作用就是初始化对象的值,而new的本质就是在调用构造器方法。

当你创建了一个有参构造器后,得手动创建一个显性得无参构造,不然当你在使用普通得new方法时会报错

创建对象的内存分析

37. 创建对象的内存分析
内存主要是栈和堆。
当一个类开始加载的时候,会先把类中的方法和常量全部放入堆中,然后遇到main()方法后把main()方法压入栈底,所有同样当你new出一个对象后,会把那个对象类的所有属性和方法放入堆中的方法区,然后会在栈中用对象名引用变量名,最后在堆中开辟出一块内存。

在主程序中你给创建的对象初始化值得时候,就会从堆中的类方法区拿着刚刚你赋的值 丢给开辟出内存的那个对象,然后给对象中的属性进行赋值。

结构图如下:
创建对象后的内存图

Java中的封装

  1. Java中的封装
    当你创建一个类后,其中的属性有很多,然后在你在程序中创建出了这个对象后,你能够直接通过类名.属性名来直接修改他的值,虽然这样看起来非常的方便,但是方便的同时安全性也降低了。所以为了保证数据的安全性,才有了封装这一概念。
    而封装就是在类的属性前面加上标识符private 这样这个属性就已经不会被随意更改了。但是随之而来的问题就是,既然都没法更改了那还怎么进行接下来的赋值操作。所以我们还需要来写额外的方法来进行读取和写入,这就是get/set方法。
    例如下:
public class Cat {
    private String catName;
    private Integer catAge;

    public String getCatName() {
        return catName;
    }

    public void setCatName(String catName) {
        this.catName = catName;
    }

    public Integer getCatAge() {
        return catAge;
    }

    public void setCatAge(Integer catAge) {
        this.catAge = catAge;
    }


    public void catCatchMonth(){
        System.out.println("The cat are catching month now!");
    }
}

Java的super和this的用法

39. Java的super和this的用法?

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.Say("hello");
    }
}

class Father{
    String name = "Same";

    public void Say(String word){
        System.out.println(this.name+"\t"+word);
    }
}


class Son extends Father{
    String name = "Jack";
}

Same	hello

就如上面例子的父类和子类,子类继承了父类,在new出对象后,子类没有Say方法所以查询父类中有没有Say方法,发现有。所以就调用父类的Say方法,此时此刻,我们注意到Say方法里面输出的名字的时候前面有一个this关键字,而这个关键字就决定了输出的结果不是子类的名字而是父类的名字。这个的原因就是this.是会调用本类中的元素,所以即使是子类使用的Say方法,但是也只会使用父类的名字。

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.Say("hello");
    }
}

class Father{
    String name = "Same";

    public Father(){
        System.out.println("父类的无惨");
    }
    public void Say(String word){
        System.out.println(this.name+"\t"+word);
    }
}
class Son extends Father{
    String name = "Jack";

    public Son(){
        System.out.println("子类的无惨");
    }
   /* public void Say(String word){
        System.out.println(this.name+"\t"+word+"\t"+word);
    }*/
}

父类的无惨
子类的无惨
Same	hello

这段代码的输出结果可能会有些疑惑,但是这样想就不会疑惑了。首先,父类和子类都创建了一个显性的无参构造。而无参构造是随着类的创建而创建的,所以即使我们在main方法中没有调用两个方法,打印的时候也会自动输出。还有一点值得注意的就是父类的无参是在子类的无参前面打印出来的。这个结果其实是隐藏代码所导致的。

 public Son(){
 //在子类的这个位置,其实隐藏了一个Super();的方法,就是这个方法调用了父类的无参构造,才导致了打印时父类无参在子类的前面
        System.out.println("子类的无惨");
    }

Super的另一个用法就是如下的例子:

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.Say("hello");
    }
}

class Father{
    String name = "Same";

    /*public Father(){
        System.out.println("父类的无惨");
    }*/

}


class Son extends Father{
    String name = "Jack";

   /* public Son(){
        System.out.println("子类的无惨");
    }*/

    public void Say(String word){
        System.out.println(this.name+"\t"+word);
    }
   /* public void Say(String word){
        System.out.println(this.name+"\t"+word+"\t"+word);
    }*/
}


Jack	hello

这个时候用this所以输出的就是子类的名字,
但是这时候如果把this换成super就是调用父类的了

 public void Say(String word){
        System.out.println(super.name+"\t"+word);
    }
Same	hello

但是在使用super的时候需要注意的一点是
当父类使用了有参构造,那么子类的无参构造就会报错,这时候有两种解决方法,其一是在父类中添加空无参构造,其二是在子类的无参构造中调用Super(父类的参数)这样的方式进行解决。

Java中的重写

  1. Java中的重写
public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.Say("hello");
    }
}
class Father{
    String name = "Same";
    public void Say(String word){
        System.out.println(this.name+"\t"+word);
    }
}

class Son extends Father{
    String name = "Jack";
    /*@Override
   public void Say(String word){
        System.out.println(this.name+"\t"+word+"\t"+word);
    }*/
}

在这段代码中父类有一个Say的方法此时在main方法中调用后理所当然的是打印出Same hello。
但是我们嫌弃父类的方法不够好所以在子类中我们重写这Say方法

    @Override
   public void Say(String word){
        System.out.println(this.name+"\t"+word+"\t"+word);
    }
}

这时候,打印出来的结果就是Jack hello hello,因为我们的子类已经重写了父类的方法,此时父类的方法已经无法适用

此时我们创建一个父类 指向父类的对象,和父类指向子类的对象

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        son.Say("hello");

        Father father = new Father();
        father.Say("hello");

        Father father1 = new Son();
        father1.Say("hello");

    }
}
class Father{
    String name = "Same";
    public void Say(String word){
        System.out.println(this.name+"\t"+word);
    }
}

class Son extends Father{
    String name = "Jack";
    @Override
   public void Say(String word){
        System.out.println(this.name+"\t"+word+"\t"+word);
    }
}
此时的结果:
Jack	hello	hello
Same	hello
Jack	hello	hello

总结的来说,当你重写了父类的方法后,当你无论你前面的对象是谁但是只要你引用的还是子类那方法就是子类重写后的方法。当然你父类创建自己的对象引用自己的方法,还是会使用你父类自己的方法。

Java的多态

41. Java的多态
在Java中对象的实际类型是确定的,但是他的引用类型是可以不确定的。比如说一个类继承了一个类,那么这两个类就有了父子关系。那么在创建对象的时候,可以创建子类的实际类型,然后用父类的引用类型。

但是在使用多态的时候要注意一些事项,比如说父类中有某方法,子类中没有,那么在使用父类型引用的时候就会调用父类中的方法,一旦在子类中重写了父类的方法,那么即使引用类型是父类,调用的方法依然是子类中重写后的方法。当然,你要是调用父类的实际类型,那么该是父类的方法还是会调用父类的方法,不会去调用子类的重写后的方法。

还有一个就是类型转换,当你的子类有父类中没有的方法时,你再使用多态的方法创建对象后时没有办法直接使用这个方法的。所以这个时候你就需要把父类强制转换成子类,这样就能使用子类的方法了。

static在Java中如何使用

42. static在Java中如何使用
在Java中static一般是指静态方法 或者静态属性,其本身是一种修饰符。首先是当使用static修饰属性的时候,可以不需要用类名就可以直接调用。同理当你使用static修饰方法后,可以不加类名就能使用。

public class Test2 {
    static int i;
    int j;
    public static void main(String[] args) {
        i = 1;
        j = 1;//这里编译器就会爆红
    }
}

static 除此之外在类中会和类一同加载,所以在写一个类的时候通常会写一个静态代码块来初始化变量。而此时我们会关心一个类加载后静态代码块的执行顺序。

public class Test2 {
    {
        System.out.println("匿名代码块");
    }
    static{
        System.out.println("静态代码块");
    }

    public Test2(){
        System.out.println("无参构造器");
    }

    public static void main(String[] args) {
        Test2 test2 = new Test2();
        System.out.println(test2);
    }
}

静态代码块
匿名代码块
无参构造器
Test2@5fd0d5ae

这时候我们可以看到静态代码块是最先输出的,其次是匿名代码块,最后是构造器的无参方法。
然后我们还可以在测试一下,看看静态代码块一共会执行几次
当我们在上面的代码添加以下代码后

Test2 test21 = new Test2();
        System.out.println(test21);

会输出
匿名代码块
无参构造器
Test2@2d98a335

我们会发现静态代码块已经不会再输出了,这是因为静态代码块是在类加载的时候就加载了,所以当你初始化一次类后静态代码块就已经随着类加载出来了,所以不会再加载第二遍。而其他的比如匿名代码块和无参构造器就会随着调用而一直执行。

抽象类

  1. 抽象类
    Java中的类中的方法一般来说是需要明确的来写出需要干什么的,但是抽象类就是一个特殊的存在,其可以不用写方法体,单纯写一个方法名。而当有类继承这个抽象类的时候,那么这个继承类就必须去实现抽象类中的抽象方法。当然如果这个继承类也是个抽象类的话就可以不用去实现抽象类中的方法,而是等继承类的继承类来实现了。

Java中的接口

  1. Java中的接口
    Java的接口可以说是一种特殊的抽象类,但是却又不是抽象类。因为类只能单继承,局限性非常大,所以才有了接口这一概念。在接口中的方法和抽象类一样是没有方法体的,要实现这个方法必须重新建立一个类去实现这个接口,并重写里面的方法。当然这里得提一下,在接口中的类修饰符都是public + abstract的,而接口中的常量的修饰符都是public + static + final的

各种内部类

45. 各种内部类

成员内部类

1)成员内部类
指在一个类中再定义一个类而这个类就是成员内部类了

public class Test2 {
    public void outWay(){
        System.out.println("外部类");
    }
    class Test2In{
        public void inWay(){
            System.out.println("内部类");
        }
    }
}


class App{
    public static void main(String[] args) {
        Test2 test2 = new Test2();
        test2.outWay();

        Test2.Test2In test2In = test2.new Test2In();
        test2In.inWay();
    }
}

外部类
内部类

局部内部类

2)局部内部类
和成员内部类基本相似只不过这个是写在方法中的

 public class Test2 {
    public void outWay(){
        System.out.println("外部类");
        class Test2In{
            public void inWay(){
                System.out.println("内部类");
            }
        }
    }

}

匿名内部类

3)匿名内部类

 public class Test2 {
    public void outWay(){
        System.out.println("匿名类");
    }

}


class App{
    public static void main(String[] args) {
        new Test2().outWay();
        }
}
  匿名类

静态内部类

4)静态内部类

public class Test2 {
    public void outWay(){
        System.out.println("外部类");
    }
   static class Test2In{
        public void inWay(){
            System.out.println("内部类");
        }
    }
}

Java中的异常的使用

  1. Java中的异常的使用
    首先异常的关键字有这几个:try catch throw throws final
    然后我们可以看一下异常的结构体系:在这里插入图片描述
    Throwable是一个超类,然后再可以分为Exception和Error
    比如说这个代码:
public class Test2 {
   static int a = 1;
   static int b = 0;

    public static void main(String[] args) {
        System.out.println(a/b);
    }

这个就会报
Exception in thread “main” java.lang.ArithmeticException: / by zero
at Test2.main(Test2.java:11)
然后程序就会自动停止了,所以这时候需要我们使用try catch语句来捕获异常

public class Test2 {
   public static void exception(int a,int b){
       try{
           System.out.println(a/b);
       }catch (ArithmeticException arithmeticException){
           System.out.println("抛出异常");
       }

   }
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        exception(a,b);
    }
}

打印出:抛出异常

如果遇到i/o流的话也可以加一句finally来关闭流

try{
           System.out.println(a/b);
       }catch (ArithmeticException arithmeticException){
           System.out.println("抛出异常");
       }finally{
           System.out.println("结束");
       }

关于throw 和throws的使用
前者是手动抛出,后者是自动抛出

public class Test2 {
   public static void exception(int a,int b){
       if(b == 0){
           throw new ArithmeticException();
       }
       /*try{
           System.out.println(a/b);
       }catch (ArithmeticException arithmeticException){
           System.out.println("抛出异常");
       }finally{
           System.out.println("结束");
       }*/

   }
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        exception(a,b);
    }
}

Exception in thread "main" java.lang.ArithmeticException
	at Test2.exception(Test2.java:9)
	at Test2.main(Test2.java:23)

这样就手动抛出了一个异常

而throws则是使用在方法上的,本身可以不用解决这个方法,但是得抛出这个方法让更高级的异常去捕获

public class Test2 {
   public void ToDo(int a,int b) throws ArithmeticException{
           System.out.println(a/b);
   }
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            new Test2().ToDo(a,b);
        }catch (ArithmeticException e){
            e.printStackTrace();
        }
    }
}

Exception in thread "main" java.lang.ArithmeticException
	at Test2.exception(Test2.java:9)
	at Test2.main(Test2.java:23)

异常的继承体系

我们从上面的关系图可以看出来,首先是有一个Throwable的超类,然后分为了可处理异常和不可以处理异常。其中可处理异常的父类为Exception,其下又分为了运行时异常(RuntimeException)和非运行时异常。而不可处理异常的父类则是Error,其下的异常只有运行时异常这一类。

运行时异常和非运行时异常的区别

运行时异常(RuntimeException)一般是指在代码编写时所犯的逻辑错误,此时即使不用throws抛出异常或使用try-catch捕获并处理异常编译器也不会报错。而编译时异常一般都是指I/O之类的异常,此时编译器会强制要求我们使用throws来抛出异常或使用try-catch捕获,不然不会通过编译。

throw和throws的区别

1、throw在方法内进行抛出,如果不是运行时异常的话,则需要在方法上加上throws来让调用者处理异常,或者加上try-catch语句用来捕获异常。执行岛throw语句后的语句块不再执行

2、throws在方法创建时进行抛出,由方法的调用者处理异常

异常处理的方法

1.异常的处理方式有两种,分别是使用throws和try…catch…finally

2.throws用在方法的声明上后接异常类名,是把异常抛给调用者进行处理

3.try…catch…finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行

a)try代码块中是可能出现异常的代码

b)catch代码块,是遇到异常,对异常进行处理的代码

c)finally代码块是无论是否发生异常,都必须执行的代码,用于释放资源

自定义异常类

问题:请使用代码实现每一个学生(Student)都有学号,姓名和分数,分数永远不能为负数如果老师给学生赋值一个负数,抛出一个自定异常

异常类代码
public class NoScoreException extends RuntimeException {
    public NoScoreException() {
    }

    public NoScoreException(String message) {
        super(message);
    }

    public NoScoreException(String message, Throwable cause) {
        super(message, cause);
    }

    public NoScoreException(Throwable cause) {
        super(cause);
    }

    public NoScoreException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

学生类代码

public class Student {
    Integer studentId;
    String studentName;
    Double score;


    public Student() {
    }

    public Student(Integer studentId, String studentName, Double score) {
        this.studentId = studentId;
        this.studentName = studentName;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "studentId=" + studentId +
                ", studentName='" + studentName + '\'' +
                ", score=" + score +
                '}';
    }

    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        if(score<0){
            throw new NoScoreException("分数不能为负数:"+score);
        }
        this.score = score;
    }
}

测试类代码

public class Test2 {
    public static void main(String[] args)  {
        Student student = new Student(1,"小李",0.0);
        student.setScore(64.5);
        System.out.println(student.getScore());
        student.setScore(-64.5);
        System.out.println(student.getScore());
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值