Java学习笔记

基础学习

一、基本数据类型

基本数据类型
整数型 byte short int long
浮点型 float double
字符型 char
布尔型 boolean

引用数据类型(今后学习)
字符串、数组、类、接口、Lambda

注意事项:

  1. 字符串不是基本类型,而是引用类型。
  2. 浮点型可能只是一个近似值,并非精确的值。
  3. 数据范围与字节数不一定相关,例如float数据范围比long更加广泛,但是float是4字节,long是8字节。
  4. 浮点数当中默认类型是double。如果一定要使用float类型,需要加上一个后缀F。
1、变量

程序运行期间,内容可以发生改变的量

创建一个变量并且使用格式:

​ 数据类型 变量名称; //创建了一个变量

​ 变量名称 = 数据值; //赋值

一步到位的格式:

​ 数据类型 变量名称 = 数据值; //创建一个变量的同时,立刻放入指定数据值

二、三种循环

计算1到100之间的偶数之和:

1、for循环

int sum = 0;//用来累加的存钱罐
        for (int i = 1;i<=100;i++){
            if (i%2==0){//如果是偶数
                sum+=i;
            }
        }

2、while循环

int sum = 0, i = 1;//用来累加的存钱罐
while (i<=100){
    i++;
    if (i%2==0){
        sum+=i;
    }
}
System.out.println(sum);

3、 do{

​ 循环体

​ 步进语句

​ }while(布尔表达式);先执行一次在进行条件判断

        int sum = 0, i = 1;//用来累加的存钱罐
        do {
           if (i%2==0){
               sum+=i;
           }
            i++;//步进语句
        }while (i<=100);
        System.out.println(sum);

4、break中断执行

5、continue:一旦执行,立刻跳过当前此循环剩余类容,马上开始下一次循环

for (int i = 1;i<9;i++){
    if (i==4){
        continue;//跳过第四,直接开始第五
    }
    System.out.println(i);
}

三、方法的调用格式

1、单独调用:方法名称(参数);
2、打印调用:System.out.println(“方法名称(参数)”);
3、赋值调用:数据类型 变量名称 = 方法名称(参数);

注意:返回值类型为void的方法只能单独调用,不能进行打印和赋值调用

只进行打印,不需要计算,也没有结果,用void。

public static void main(String[] args) {
    //单独调用
    sum(10,20);
    System.out.println("--------------");

    //打印调用
    System.out.println(sum(10,20));
    System.out.println("---------------");

    //赋值调用
    int number = sum(10,20);
    number+=100;
    System.out.println("变量的值"+number);
}
public static int sum(int a, int b){
    System.out.println("方法执行了");
    int result = a+b;
    return result;
}
image-20201228190225876
4、有参数和无参数

/*
有参数:小括号当中有内容,当一个方法需要一些数据条件,才能完成任务的时候,就是有参数。
例如两个数字相加,必须知道两个数字是各自多少,才能相加。

无参数:小括号当中留空。一个方法不需要任何数据条件,自己就能独立完成任务,就是无参数。
例如定义一个方法,打印固定10次HelloWorld。
*/
public class Demo03MethodParam {

public static void main(String[] args) {
    method1(10, 20);
    System.out.println("==============");
    method2();
}

// 两个数字相乘,做乘法,必须知道两个数字各自是多少,否则无法进行计算
// 有参数
public static void method1(int a, int b) {
    int result = a * b;
    System.out.println("结果是:" + result);
}

// 例如打印输出固定10次文本字符串
public static void method2() {
    for (int i = 0; i < 10; i++) {
        System.out.println("Hello, World!" + i);
    }
}
5、有返回值和无返回值

/*
题目要求:定义一个方法,用来【求出】两个数字之和。(你帮我算,算完之后把结果告诉我。)
题目变形:定义一个方法,用来【打印】两个数字之和。(你来计算,算完之后你自己负责显示结果,不用告诉我。)

注意事项:
对于有返回值的方法,可以使用单独调用、打印调用或者赋值调用。
但是对于无返回值的方法,只能使用单独调用,不能使用打印调用或者赋值调用。
 */
public class Demo04MethodReturn {

    public static void main(String[] args) {
        // 我是main方法,我来调用你。
        // 我调用你,你来帮我计算一下,算完了之后,把结果告诉我的num变量
        int num = getSum(10, 20);
        System.out.println("返回值是:" + num);
        System.out.println("==============");

        printSum(100, 200);
        System.out.println("==============");

        System.out.println(getSum(2, 3)); // 正确写法
        getSum(3, 5); // 正确写法,但是返回值没有用到
        System.out.println("==============");

        // 对于void没有返回值的方法,只能单独,不能打印或者赋值
//        System.out.println(printSum(2, 3)); // 错误写法!
//        System.out.println(void);

//        int num2 = printSum(10, 20); // 错误写法!
//        int num3 = void;
//        void num4 = void;
    }

    // 我是一个方法,我负责两个数字相加。
    // 我有返回值int,谁调用我,我就把计算结果告诉谁
    public static int getSum(int a, int b) {
        int result = a + b;
        return result;
    }

    // 我是一个方法,我负责两个数字相加。
    // 我没有返回值,不会把结果告诉任何人,而是我自己进行打印输出。
    public static void printSum(int a, int b) {
        int result = a + b;
        System.out.println("结果是:" + result);
    }
6、两个数字是否相同

是否两字出现就是布尔值(boolean)

package cn.itcast.day04.demo03;

/*
题目要求:
定义一个方法,用来判断两个数字是否相同。
 */
public class Demo01MethodSame {

    public static void main(String[] args) {
        System.out.println(isSame(10, 20)); // false
        System.out.println(isSame(20, 20)); // true
    }

    /*
    三要素:
    返回值类型:boolean
    方法名称:isSame
    参数列表:int a, int b
     */
    public static boolean isSame(int a, int b) {
        /*boolean same;
        if (a == b) {
            same = true;
        } else {
            same = false;
        }*/

        // boolean same = a == b ? true : false;

        // boolean same = a == b;

        return a == b;
    }

}

7、方法的注意事项

​ 1、方法应该定义在类当中,但是不能再方法当中在定义方法,不能嵌套。

​ 2、方法定义的前后顺序无所谓

​ 3、方法定义之后不会执行,如果希望执行,一定要调用:单独调用、打印调用、赋值调用。

​ 4.、如果方法有返回值,那么必须写上“return 返回值;”,不能没有。

​ 5、return后面的返回值数据,必须和方法的返回值类型,对应起来。

​ 6、对于一个void没有返回值的方法,不能写return后面的返回值,只能写return自己。

​ 7、对于void方法当中最后一行的return可以省略不写。

​ 8、一个方法当中可以有多个return语句,但是必须保证同时只有一个会被执行到,两个return不能连写。

public class Demo04MethodNotice {

    public static int method1() {
        return 10;
    }

    public static void method2() {
//        return 10; // 错误的写法!方法没有返回值,return后面就不能写返回值。
        return; // 没有返回值,只是结束方法的执行而已。
    }

    public static void method3() {
        System.out.println("AAA");
        System.out.println("BBB");
//        return; // 最后一行的return可以省略不写。
    }

    public static int getMax(int a, int b) {
        /*int max;
        if (a > b) {
            max = a;
        } else {
            max = b;
        }
        return max;*/

        if (a > b) {
            return a;
        } else {
            return b;
        }
    }

}

四、方法的重载

对于功能类似的方法来说,因为参数列表不一样,却需要记住那么多不同的方法名称,太麻烦。

方法的重载(Overload):多个方法的名称一样,但是参数列表不一样。
好处:只需要记住唯一一个方法名称,就可以实现类似的多个功能。

方法重载与下列因素相关:

  1. 参数个数不同
  2. 参数类型不同
  3. 参数的多类型顺序不同

方法重载与下列因素无关:

  1. 与参数的名称无关
  2. 与方法的返回值类型无关
public class Demo01MethodOverload {

    public static void main(String[] args) {
        /*System.out.println(sumTwo(10, 20)); // 30
        System.out.println(sumThree(10, 20, 30)); // 60
        System.out.println(sumFour(10, 20, 30, 40)); // 100*/

        System.out.println(sum(10, 20)); // 两个参数的方法
        System.out.println(sum(10, 20, 30)); // 三个参数的方法
        System.out.println(sum(10, 20, 30, 40)); // 四个参数的方法
//        System.out.println(sum(10, 20, 30, 40, 50)); // 找不到任何方法来匹配,所以错误!

        sum(10, 20);
    }

    public static int sum(int a, double b) {
        return (int) (a + b);
    }

    public static int sum(double a, int b) {
        return (int) (a + b);
    }

    public static int sum(int a, int b) {
        System.out.println("有2个参数的方法执行!");
        return a + b;
    }

    // 错误写法!与方法的返回值类型无关
//    public static double sum(int a, int b) {
//        return a + b + 0.0;
//    }

    // 错误写法!与参数的名称无关
//    public static int sum(int x, int y) {
//        return x + y;
//    }

    public static int sum(double a, double b) {
        return (int) (a + b);
    }

    public static int sum(int a, int b, int c) {
        System.out.println("有3个参数的方法执行!");
        return a + b + c;
    }

    public static int sum(int a, int b, int c, int d) {
        System.out.println("有4个参数的方法执行!");
        return a + b + c + d;
    }

}

五、数组

1、概念和特点

​ 1、概念是一种容器,可以同时存放多个数据值

​ 2、数组的特点: 1.数组是一种引用数据类型

​ 2.数组当中的多个数据,类型必须统一

​ 3.数组的长度在程序运行期间不可改变

​ 3、数组的初始化:在内存当中创建一个数组,并且向其中赋予一些默认值。

​ 两种常见的初始化方式:1.动态初始化(指定长度)

​ 2.静态初始化(指定长度)

数据类型[] 数组名称 = new 数据类型[数组长度];

解析含义:
左侧数据类型:也就是数组当中保存的数据,全都是统一的什么类型
左侧的中括号:代表我是一个数组
左侧数组名称:给数组取一个名字
右侧的new:代表创建数组的动作
右侧数据类型:必须和左边的数据类型保持一致
右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字

2、动态初始化和静态初始化的区别

动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素个数。
静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。

静态初始化基本格式:
数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, … };

注意事项:
虽然静态初始化没有直接告诉长度,但是根据大括号里面的元素具体内容,也可以自动推算出来长度。

动态初始化:

 public static void main(String[] args) {
        // 创建一个数组,里面可以存放300个int数据
        // 格式:数据类型[] 数组名称 = new 数据类型[数组长度];
        int[] arrayA = new int[300];

        // 创建一个数组,能存放10个double类型的数据
        double[] arrayB = new double[10];

        // 创建一个数组,能存放5个字符串
        String[] arrayC = new String[5];
    }

静态初始化:使用静态初始化数组的时候,格式还可以省略一下。

标准格式:
数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, … };

省略格式:
数据类型[] 数组名称 = { 元素1, 元素2, … };

注意事项:

  1. 静态初始化没有直接指定长度,但是仍然会自动推算得到长度。
  2. 静态初始化标准格式可以拆分成为两个步骤。
  3. 动态初始化也可以拆分成为两个步骤。
  4. 静态初始化一旦使用省略格式,就不能拆分成为两个步骤了。

使用建议:
如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体的内容,用静态初始化。

 public static void main(String[] args) {
        // 直接创建一个数组,里面装的全都是int数字,具体为:5、15、25
        int[] arrayA = new int[] { 5, 15, 25, 40 };

        // 创建一个数组,用来装字符串:"Hello"、"World"、"Java"
        String[] arrayB = new String[] { "Hello", "World", "Java" };
    }

3、获取数组元素

直接打印数组名称,得到的是数组对应的:内存地址哈希值。
二进制:01
十进制:0123456789
16进制:0123456789abcdef

访问数组元素的格式:数组名称[索引值]
索引值:就是一个int数字,代表数组当中元素的编号。
【注意】索引值从0开始,一直到“数组的长度-1”为止。

public static void main(String[] args) {
        // 静态初始化的省略格式
        int[] array = { 10, 20, 30 };

        System.out.println(array); // [I@75412c2f

        // 直接打印数组当中的元素
        System.out.println(array[0]); // 10
        System.out.println(array[1]); // 20
        System.out.println(array[2]); // 30
        System.out.println("=============");

        // 也可以将数组当中的某一个单个元素,赋值交给变量
        int num = array[1];
        System.out.println(num); // 20
    }
4、访问数组元素进行赋值

使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值。规则如下:
如果是整数类型,那么默认为0;
如果是浮点类型,那么默认为0.0;
如果是字符类型,那么默认为’\u0000’;
如果是布尔类型,那么默认为false;
如果是引用类型,那么默认为null。

注意事项:
静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为了大括号当中的具体数值。

public static void main(String[] args) {
        // 动态初始化一个数组
        int[] array = new int[3];

        System.out.println(array); // 内存地址值
        System.out.println(array[0]); // 0
        System.out.println(array[1]); // 0
        System.out.println(array[2]); // 0
        System.out.println("=================");

        // 将数据123赋值交给数组array当中的1号元素
        array[1] = 123;
        System.out.println(array[0]); // 0
        System.out.println(array[1]); // 123
        System.out.println(array[2]); // 0
4.1、获取数组长度

如何获取数组的长度,格式:
数组名称.length

这将会得到一个int数字,代表数组的长度。

数组一旦创建,程序运行期间,长度不可改变。

public static void main(String[] args) {
        int[] arrayA = new int[3];

        int[] arrayB = {10, 20, 30, 3, 5, 4, 6, 7, 8, 8, 65, 4, 44, 6, 10, 3, 5, 4, 6, 7, 8, 8, 65, 4};
        int len = arrayB.length;
        System.out.println("arrayB数组的长度是:" + len);
        System.out.println("=============");

        int[] arrayC = new int[3];
        System.out.println(arrayC.length); // 3
        arrayC = new int[5];
        System.out.println(arrayC.length); // 5
    }
5、Java中的内存划分

1、栈(Stack):存放的都是方法中的局部变量,方法的运行一定要在栈当中运行,

​ 局部变量:方法的参数,或者是方法()内部的变量

​ 作用域:一旦超出作用域,立刻从栈内存中消失。

2、堆(Heap):凡是new出来的东西,都在堆当中。

​ 堆内存里面的东西都有一个地址值:16进制

​ 堆内存里面的东西,都有默认值。规则:

​ 如果是整数 默认为0

​ 如果是浮点数 默认为0.0

​ 如果是字符 默认为‘\u0000’

​ 如果是布尔 默认为false

​ 如果是引用类型 默认为null

3、方法区(Method Area):存储.class相关信息,包含方法的信息

4、本地方法栈(Native Method Stack):与操作系统相关

5、寄存器(pc Register):与cpu相关

一个数组的内存图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FD0E8Tya-1624356413461)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20201229175230226.png)]

6、遍历数组

遍历数组,说的就是对数组当中的每一个元素进行逐一、挨个儿处理。默认的处理方式就是打印输出。

    public static void main(String[] args) {
        int[] array = { 15, 25, 30, 40, 50, 60, 75 };

        // 首先使用原始方式
        System.out.println(array[0]); // 15
        System.out.println(array[1]); // 25
        System.out.println(array[2]); // 30
        System.out.println(array[3]); // 40
        System.out.println(array[4]); // 50
        System.out.println(array[5]); // 50
        System.out.println("=================");

        // 使用循环,次数其实就是数组的长度。
        for (int i = 0; i < 6; i++) {
            System.out.println(array[i]);
        }
        System.out.println("=================");

//        int len = array.length; // 长度
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
7、数组地址值传递

数组可以作为方法的参数。
当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值。

一个方法可以有0、1、多个参数;但是只能有0或者1个返回值,不能有多个返回值。
如果希望一个方法当中产生了多个结果数据进行返回,怎么办?
解决方案:使用一个数组作为返回值类型即可。

任何数据类型都能作为方法的参数类型,或者返回值类型。

数组作为方法的参数,传递进去的其实是数组的地址值。
数组作为方法的返回值,返回的其实也是数组的地址值。

public static void main(String[] args) {
        int[] result = calculate(10, 20, 30);

        System.out.println("main方法接收到的返回值数组是:");
        System.out.println(result); // 地址值

        System.out.println("总和:" + result[0]);
        System.out.println("平均数:" + result[1]);
    }

    public static int[] calculate(int a, int b, int c) {
        int sum = a + b + c; // 总和
        int avg = sum / 3; // 平均数
        // 两个结果都希望进行返回

        // 需要一个数组,也就是一个塑料兜,数组可以保存多个结果
        /*
        int[] array = new int[2];
        array[0] = sum; // 总和
        array[1] = avg; // 平均数
        */

        int[] array = { sum, avg };
        System.out.println("calculate方法内部数组是:");
        System.out.println(array); // 地址值
        return array;
    }

六、面向对象

1、面向对象和面向过程

面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲力亲为,详细处理每一个细节。
面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做事儿。

public static void main(String[] args) {
        int[] array = { 10, 20, 30, 40, 50, 60 };

        // 要求打印格式为:[10, 20, 30, 40, 50]
        // 使用面向过程,每一个步骤细节都要亲力亲为。
        System.out.print("[");
        for (int i = 0; i < array.length; i++) {
            if (i == array.length - 1) { // 如果是最后一个元素
                System.out.println(array[i] + "]");
            } else { // 如果不是最后一个元素
                System.out.print(array[i] + ", ");
            }
        }
        System.out.println("==============");

        // 使用面向对象
        // 找一个JDK给我们提供好的Arrays类,
        // 其中有一个toString方法,直接就能把数组变成想要的格式的字符串
        System.out.println(Arrays.toString(array));
    }
2、对象的创建及其使用

通常情况下,一个类并不能直接使用,需要根据类创建一个对象,才能使用。

  1. 导包:也就是指出需要使用的类,在什么位置。
    import 包名称.类名称;
    import cn.itcast.day06.demo01.Student;
    对于和当前类属于同一个包的情况,可以省略导包语句不写。

  2. 创建,格式:
    类名称 对象名 = new 类名称();
    Student stu = new Student();

  3. 使用,分为两种情况:
    使用成员变量:对象名.成员变量名
    使用成员方法:对象名.成员方法名(参数)
    (也就是,想用谁,就用对象名点儿谁。)

注意事项:
如果成员变量没有进行赋值,那么将会有一个默认值,规则和数组一样。

类Student

public class Student {
    String name;
    int age;

    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉觉");
    }
    public void study(){
        System.out.println("学习");
    }

创建一个Demo02Student来使用Student类

  public static void main(String[] args) {
        // 1. 导包。
        // 我需要使用的Student类,和我自己Demo02Student位于同一个包下,所以省略导包语句不写

        // 2. 创建,格式:
        // 类名称 对象名 = new 类名称();
        // 根据Student类,创建了一个名为stu的对象
        Student stu = new Student();

        // 3. 使用其中的成员变量,格式:
        // 对象名.成员变量名
        System.out.println(stu.name); // null
        System.out.println(stu.age); // 0
        System.out.println("=============");

        // 改变对象当中的成员变量数值内容
        // 将右侧的字符串,赋值交给stu对象当中的name成员变量
        stu.name = "赵丽颖";
        stu.age = 18;
        System.out.println(stu.name); // 赵丽颖
        System.out.println(stu.age); // 18
        System.out.println("=============");

        // 4. 使用对象的成员方法,格式:
        // 对象名.成员方法名()
        stu.eat();
        stu.sleep();
        stu.study();
    }
2.1一个对象的内存图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wcOO1qEM-1624356413462)(F:\zzz黑马学习\image-20201231163230672.png)]

3、局部变量和成员变量
  1. 定义的位置不一样【重点】
    局部变量:在方法的内部
    成员变量:在方法的外部,直接写在类当中

  2. 作用范围不一样【重点】
    局部变量:只有方法当中才可以使用,出了方法就不能再用
    成员变量:整个类全都可以通用。

  3. 默认值不一样【重点】
    局部变量:没有默认值,如果要想使用,必须手动进行赋值
    成员变量:如果没有赋值,会有默认值,规则和数组一样

  4. 内存的位置不一样(了解)
    局部变量:位于栈内存
    成员变量:位于堆内存

  5. 生命周期不一样(了解)
    局部变量:随着方法进栈而诞生,随着方法出栈而消失
    成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失

public class Demo01VariableDifference {

    String name; // 成员变量

    public void methodA() {
        int num = 20; // 局部变量
        System.out.println(num);
        System.out.println(name);
    }

    public void methodB(int param) { // 方法的参数就是局部变量
        // 参数在方法调用的时候,必然会被赋值的。
        System.out.println(param);

        int age; // 局部变量
//        System.out.println(age); // 没赋值不能用

//        System.out.println(num); // 错误写法!
        System.out.println(name);
    }
4、面向对象三大特征

面向对象三大特征:封装、继承、多态。

封装性在Java当中的体现:

  1. 方法就是一种封装
  2. 关键字private也是一种封装

封装就是将一些细节信息隐藏起来,对于外界不可见。

 public static void main(String[] args) {
        int[] array = {5, 15, 25, 20, 100};

        int max = getMax(array);
        System.out.println("最大值:" + max);
    }

    // 给我一个数组,我还给你一个最大值
    public static int getMax(int[] array) {
        int max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
        }
        return max;
    }

问题描述:定义Person的年龄时,无法阻止不合理的数值被设置进来。
解决方案:用private关键字将需要保护的成员变量进行修饰。

一旦使用了private进行修饰,那么本类当中仍然可以随意访问。
但是!超出了本类范围之外就不能再直接访问了。

间接访问private成员变量,就是定义一对儿Getter/Setter方法

必须叫setXxx或者是getXxx命名规则。
对于Getter来说,不能有参数,返回值类型和成员变量对应;
对于Setter来说,不能有返回值,参数类型和成员变量对应。

package mianxiangduixiang.Demo03;

public class Person {
    String name;
    private int age;

    public void show(){
        System.out.println("我叫"+name+"今年"+age+"岁了");
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age>0){
            this.age = age;
        }else {
            System.err.println("请输入正确的数据");
        }

    }
}

package mianxiangduixiang.Demo03;

public class Demo03Persong {
    public static void main(String[] args) {
        Person one = new Person();

        one.name = "5555";
        one.setAge(-2);
        one.show();

    }
}

对于基本类型当中的boolean值,Getter方法一定要写成isXxx的形式,而setXxx规则不变。

4.1_this关键字的作用

当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量。
如果需要访问本类当中的成员变量,需要使用格式:
this.成员变量名

“通过谁调用的方法,谁就是this。”

String name; // 我自己的名字

    // 参数name是对方的名字
    // 成员变量name是自己的名字
    public void sayHello(String name) {
        System.out.println(name + ",你好。我是" + this.name);
        System.out.println(this);
    }

4.2_构造方法

构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。
格式:
public 类名称(参数类型 参数名称) {
方法体
}

注意事项:

  1. 构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样

  2. 构造方法不要写返回值类型,连void都不写

  3. 构造方法不能return一个具体的返回值

  4. 如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。
    public Student() {}

  5. 一旦编写了至少一个构造方法,那么编译器将不再赠送。

  6. 构造方法也是可以进行重载的。
    重载:方法名称相同,参数列表不同。

public class Demo02Student {

    public static void main(String[] args) {
        Student stu1 = new Student(); // 无参构造
        System.out.println("============");

        Student stu2 = new Student("赵丽颖", 20); // 全参构造
        System.out.println("姓名:" + stu2.getName() + ",年龄:" + stu2.getAge());
        // 如果需要改变对象当中的成员变量数据内容,仍然还需要使用setXxx方法
        stu2.setAge(21); // 改变年龄
        System.out.println("姓名:" + stu2.getName() + ",年龄:" + stu2.getAge());

    }
public class Student {
    private String name;
    private int age;
    public Student(){

    }
    public Student(String name,int age){
        System.out.println("构造方法执行啦");
        this.age = age;
        this.name = name;
//        System.out.println(getAge()+getName());
    }

    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;
    }

七、各种类

1、Scanner类

Scanner类的功能:可以实现键盘输入数据,到程序当中。

引用类型的一般使用步骤:

  1. 导包
    import 包路径.类名称;
    如果需要使用的目标类,和当前类位于同一个包下,则可以省略导包语句不写。
    只有java.lang包下的内容不需要导包,其他的包都需要import语句。

  2. 创建
    类名称 对象名 = new 类名称();

  3. 使用
    对象名.成员方法名()

获取键盘输入的一个int数字:int num = sc.nextInt();
获取键盘输入的一个字符串:String str = sc.next();

 public static void main(String[] args) {
        // 2. 创建
        // 备注:System.in代表从键盘进行输入
        Scanner sc = new Scanner(System.in);

        // 3. 获取键盘输入的int数字
        int num = sc.nextInt();
        System.out.println("输入的int数字是:" + num);

        // 4. 获取键盘输入的字符串
        String str = sc.next();
        System.out.println("输入的字符串是:" + str);
    }

2、匿名对象的说明

创建对象的标准格式:
类名称 对象名 = new 类名称();

匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。
new 类名称();

注意事项:匿名对象只能使用唯一的一次,下次再用不得不再创建一个新对象。
使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。

public static void main(String[] args) {
        // 左边的one就是对象的名字
        Person one = new Person();
        one.name = "高圆圆";
        one.showName(); // 我叫高圆圆
        System.out.println("===============");

        // 匿名对象
        new Person().name = "赵又廷";
        new Person().showName(); // 我叫:null
    }
3、Random类

Random类用来生成随机数字。使用起来也是三个步骤:

  1. 导包
    import java.util.Random;

  2. 创建
    Random r = new Random(); // 小括号当中留空即可

  3. 使用
    获取一个随机的int数字(范围是int所有范围,有正负两种):int num = r.nextInt()
    获取一个随机的int数字(参数代表了范围,左闭右开区间):int num = r.nextInt(3)
    实际上代表的含义是:[0,3),也就是0~2

  public static void main(String[] args) {
        Random r = new Random();

        for (int i = 0; i < 100; i++) {
            int num = r.nextInt(10); // 范围实际上是0~9
            System.out.println(num);
        }
    }

4、Array类

题目:
定义一个数组,用来存储3个Person对象。

数组有一个缺点:一旦创建,程序运行期间长度不可以发生改变。

public static void main(String[] args) {
        Demo06Person[] array = new Demo06Person[3];


        Demo06Person one = new Demo06Person("迪丽热巴", 18);
        Demo06Person two = new Demo06Person("古力娜扎", 28);
        Demo06Person three = new Demo06Person("玛尔扎哈", 38);

        // 将one当中的地址值赋值到数组的0号元素位置
        array[0] = one;
        array[1] = two;
        array[2] = three;

        System.out.println(array[0]); // 地址值
        System.out.println(array[1]); // 地址值
        System.out.println(array[2]); // 地址值

        System.out.println(array[1].getName()); // 古力娜扎
    }
1、ArrayList

数组的长度不可以发生改变。
但是ArrayList集合的长度是可以随意变化的。

对于ArrayList来说,有一个尖括号代表泛型。
泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。
注意:泛型只能是引用类型,不能是基本类型。

注意事项:
对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。
如果内容是空,得到的是空的中括号:[]

public static void main(String[] args) {
        // 创建了一个ArrayList集合,集合的名称是list,里面装的全都是String字符串类型的数据
        // 备注:从JDK 1.7+开始,右侧的尖括号内部可以不写内容,但是<>本身还是要写的。
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list); // []

        // 向集合当中添加一些数据,需要用到add方法。
        list.add("赵丽颖");
        System.out.println(list); // [赵丽颖]

        list.add("迪丽热巴");
        list.add("古力娜扎");
        list.add("玛尔扎哈");
        System.out.println(list); // [赵丽颖, 迪丽热巴, 古力娜扎, 玛尔扎哈]

//        list.add(100); // 错误写法!因为创建的时候尖括号泛型已经说了是字符串,添加进去的元素就必须都是字符串才行
    }

ArrayList当中的常用方法有:

public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致。返回值代表添加是否成功。
备注:对于ArrayList集合来说,add添加动作一定是成功的,所以返回值可用可不用。
但是对于其他集合(今后学习)来说,add添加动作不一定成功。

public E get(int index):从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素。

public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。

public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数。

public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list); // []

        // 向集合中添加元素:add
        boolean success = list.add("柳岩");
        System.out.println(list); // [柳岩]
        System.out.println("添加的动作是否成功:" + success); // true

        list.add("高圆圆");
        list.add("赵又廷");
        list.add("李小璐");
        list.add("贾乃亮");
        System.out.println(list); // [柳岩, 高圆圆, 赵又廷, 李小璐, 贾乃亮]

        // 从集合中获取元素:get。索引值从0开始
        String name = list.get(2);
        System.out.println("第2号索引位置:" + name); // 赵又廷

        // 从集合中删除元素:remove。索引值从0开始。
        String whoRemoved = list.remove(3);
        System.out.println("被删除的人是:" + whoRemoved); // 李小璐
        System.out.println(list); // [柳岩, 高圆圆, 赵又廷, 贾乃亮]

        // 获取集合的长度尺寸,也就是其中元素的个数
        int size = list.size();
        System.out.println("集合的长度是:" + size);
    }

如果希望向集合ArrayList当中存储基本类型数据,必须使用基本类型对应的“包装类”。

基本类型 包装类(引用类型,包装类都位于java.lang包下)
byte Byte
short Short
int Integer 【特殊】
long Long
float Float
double Double
char Character 【特殊】
boolean Boolean

从JDK 1.5+开始,支持自动装箱、自动拆箱。

自动装箱:基本类型 --> 包装类型
自动拆箱:包装类型 --> 基本类型

public class Demo05ArrayListBasic {

    public static void main(String[] args) {
        ArrayList<String> listA = new ArrayList<>();
        // 错误写法!泛型只能是引用类型,不能是基本类型
//        ArrayList<int> listB = new ArrayList<>();

        ArrayList<Integer> listC = new ArrayList<>();
        listC.add(100);
        listC.add(200);
        System.out.println(listC); // [100, 200]

        int num = listC.get(1);
        System.out.println("第1号元素是:" + num);
    }

八、字符串

java.lang.String类代表字符串。
API当中说:Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
其实就是说:程序当中所有的双引号字符串,都是String类的对象。(就算没有new,也照样是。)

字符串的特点:

  1. 字符串的内容永不可变。【重点】
  2. 正是因为字符串不可改变,所以字符串是可以共享使用的。
  3. 字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组。

创建字符串的常见3+1种方式。
三种构造方法:
public String():创建一个空白字符串,不含有任何内容。
public String(char[] array):根据字符数组的内容,来创建对应的字符串。
public String(byte[] array):根据字节数组的内容,来创建对应的字符串。
一种直接创建:
String str = “Hello”; // 右边直接用双引号

注意:直接写上双引号,就是字符串对象。

public static void main(String[] args) {
        // 使用空参构造
        String str1 = new String(); // 小括号留空,说明字符串什么内容都没有。
        System.out.println("第1个字符串:" + str1);

        // 根据字符数组创建字符串
        char[] charArray = { 'A', 'B', 'C' };
        String str2 = new String(charArray);
        System.out.println("第2个字符串:" + str2);

        // 根据字节数组创建字符串
        byte[] byteArray = { 97, 98, 99 };
        String str3 = new String(byteArray);
        System.out.println("第3个字符串:" + str3);

        // 直接创建
        String str4 = "Hello";
        System.out.println("第4个字符串:" + str4);
    }

字符串常量池:程序当中直接写上的双引号字符串,就在字符串常量池中。

对于基本类型来说,==是进行数值的比较。
对于引用类型来说,==是进行**【地址值】**的比较。

 public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";

        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);

        System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // false
        System.out.println(str2 == str3); // false
    }
1、字符串比较

==是进行对象的地址值比较,如果确实需要字符串的内容比较,可以使用两个方法:

public boolean equals(Object obj):参数可以是任何对象,只有参数是一个字符串并且内容相同的才会给true;否则返回false。
注意事项:

  1. 任何对象都能用Object进行接收。
  2. equals方法具有对称性,也就是a.equals(b)和b.equals(a)效果一样。
  3. 如果比较双方一个常量一个变量,推荐把常量字符串写在前面。
    推荐:“abc”.equals(str) 不推荐:str.equals(“abc”)

public boolean equalsIgnoreCase(String str):忽略大小写,进行内容比较。

public class Demo01StringEquals {

    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "Hello";
        char[] charArray = {'H', 'e', 'l', 'l', 'o'};
        String str3 = new String(charArray);

        System.out.println(str1.equals(str2)); // true
        System.out.println(str2.equals(str3)); // true
        System.out.println(str3.equals("Hello")); // true
        System.out.println("Hello".equals(str1)); // true

        String str4 = "hello";
        System.out.println(str1.equals(str4)); // false
        System.out.println("=================");

        String str5 = null;
        System.out.println("abc".equals(str5)); // 推荐:false
//        System.out.println(str5.equals("abc")); // 不推荐:报错,空指针异常NullPointerException
        System.out.println("=================");

        String strA = "Java";
        String strB = "java";
        System.out.println(strA.equals(strB)); // false,严格区分大小写
        System.out.println(strA.equalsIgnoreCase(strB)); // true,忽略大小写

        // 注意,只有英文字母区分大小写,其他都不区分大小写
        System.out.println("abc一123".equalsIgnoreCase("abc壹123")); // false
    }
2、字符串的获取方法

String当中与获取相关的常用方法有:

public int length():获取字符串当中含有的字符个数,拿到字符串长度。
public String concat(String str):将当前字符串和参数字符串拼接成为返回值新的字符串。
public char charAt(int index):获取指定索引位置的单个字符。(索引从0开始。)
public int indexOf(String str):查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1值。

 public static void main(String[] args) {
        // 获取字符串的长度
        int length = "asdasfeutrvauevbueyvb".length();
        System.out.println("字符串的长度是:" + length);

        // 拼接字符串
        String str1 = "Hello";
        String str2 = "World";
        String str3 = str1.concat(str2);
        System.out.println(str1); // Hello,原封不动
        System.out.println(str2); // World,原封不动
        System.out.println(str3); // HelloWorld,新的字符串
        System.out.println("==============");

        // 获取指定索引位置的单个字符
        char ch = "Hello".charAt(1);
        System.out.println("在1号索引位置的字符是:" + ch);
        System.out.println("==============");

        // 查找参数字符串在本来字符串当中出现的第一次索引位置
        // 如果根本没有,返回-1值
        String original = "HelloWorldHelloWorld";
        int index = original.indexOf("llo");
        System.out.println("第一次索引值是:" + index); // 2

        System.out.println("HelloWorld".indexOf("abc")); // -1
    }
3、字符串的截取方法

字符串的截取方法:

public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串。
public String substring(int begin, int end):截取从begin开始,一直到end结束,中间的字符串。
备注:[begin,end),包含左边,不包含右边。

public static void main(String[] args) {
        String str1 = "HelloWorld";
        String str2 = str1.substring(5);
        System.out.println(str1); // HelloWorld,原封不动
        System.out.println(str2); // World,新字符串
        System.out.println("================");

        String str3 = str1.substring(4, 7);
        System.out.println(str3); // oWo
        System.out.println("================");

        // 下面这种写法,字符串的内容仍然是没有改变的
        // 下面有两个字符串:"Hello","Java"
        // strA当中保存的是地址值。
        // 本来地址值是Hello的0x666,
        // 后来地址值变成了Java的0x999
        String strA = "Hello";
        System.out.println(strA); // Hello
        strA = "Java";
        System.out.println(strA); // Java
    }
4、字符串的转换方法

public char[] toCharArray():将当前字符串拆分成为字符数组作为返回值。
public byte[] getBytes():获得当前字符串底层的字节数组。
public String replace(CharSequence oldString, CharSequence newString):
将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串。
备注:CharSequence意思就是说可以接受字符串类型。

    public static void main(String[] args) {
        // 转换成为字符数组
        char[] chars = "Hello".toCharArray();
        System.out.println(chars[0]); // H
        System.out.println(chars.length); // 5
        System.out.println("==============");

        // 转换成为字节数组
        byte[] bytes = "abc".getBytes();
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
        }
        System.out.println("==============");

        // 字符串的内容替换
        String str1 = "How do you do?";
        String str2 = str1.replace("o", "*");
        System.out.println(str1); // How do you do?
        System.out.println(str2); // H*w d* y*u d*?
        System.out.println("==============");
5、字符串的分割方法

分割字符串的方法:
public String[] split(String regex):按照参数的规则,将字符串切分成为若干部分。

注意事项:
split方法的参数其实是一个“正则表达式”,今后学习
今天要注意**:如果按照英文句点“.”进行切分,必须写"\\."(两个反斜杠)**

public static void main(String[] args) {
        String str1 = "aaa,bbb,ccc";
        String[] array1 = str1.split(",");
        for (int i = 0; i < array1.length; i++) {
            System.out.println(array1[i]);
        }
        System.out.println("===============");

        String str2 = "aaa bbb ccc";
        String[] array2 = str2.split(" ");
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i]);
        }
        System.out.println("===============");

        String str3 = "XXX.YYY.ZZZ";
        String[] array3 = str3.split("\\.");
        System.out.println(array3.length); // 0
        for (int i = 0; i < array3.length; i++) {
            System.out.println(array3[i]);
        }
    }

题目:
键盘输入一个字符串,并且统计其中各种字符出现的次数。
种类有:大写字母、小写字母、数字、其他

思路:

  1. 既然用到键盘输入,肯定是Scanner
  2. 键盘输入的是字符串,那么:String str = sc.next();
  3. 定义四个变量,分别代表四种字符各自的出现次数。
  4. 需要对字符串一个字、一个字检查,String–>char[],方法就是toCharArray()
  5. 遍历char[]字符数组,对当前字符的种类进行判断,并且用四个变量进行++动作。
  6. 打印输出四个变量,分别代表四种字符出现次数。
  public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String input = sc.next(); // 获取键盘输入的一个字符串

        int countUpper = 0; // 大写字母
        int countLower = 0; // 小写字母
        int countNumber = 0; // 数字
        int countOther = 0; // 其他字符

        char[] charArray = input.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            char ch = charArray[i]; // 当前单个字符
            if ('A' <= ch && ch <= 'Z') {
                countUpper++;
            } else if ('a' <= ch && ch <= 'z') {
                countLower++;
            } else if ('0' <= ch && ch <= '9') {
                countNumber++;
            } else {
                countOther++;
            }
        }

        System.out.println("大写字母有:" + countUpper);
        System.out.println("小写字母有:" + countLower);
        System.out.println("数字有:" + countNumber);
        System.out.println("其他字符有:" + countOther);
    }
6、Static方法

一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。

如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它。

无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()


注意事项:

  1. 静态不能直接访问非静态。
    原因:因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
    “先人不知道后人,但是后人知道先人。”
  2. 静态方法当中不能用this。
    原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。
    public static void main(String[] args) {
        MyClass obj = new MyClass(); // 首先创建对象
        // 然后才能使用没有static关键字的内容
        obj.method();

        // 对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用。
        obj.methodStatic(); // 正确,不推荐,这种写法在编译之后也会被javac翻译成为“类名称.静态方法名”
        MyClass.methodStatic(); // 正确,推荐

        // 对于本来当中的静态方法,可以省略类名称
        myMethod();
        Demo02StaticMethod.myMethod(); // 完全等效
    }

    public static void myMethod() {
        System.out.println("自己的方法!");
    }
public class MyClass {

    int num; // 成员变量
    static int numStatic; // 静态变量

    // 成员方法
    public void method() {
        System.out.println("这是一个成员方法。");
        // 成员方法可以访问成员变量
        System.out.println(num);
        // 成员方法可以访问静态变量
        System.out.println(numStatic);
    }

    // 静态方法
    public static void methodStatic() {
        System.out.println("这是一个静态方法。");
        // 静态方法可以访问静态变量
        System.out.println(numStatic);
        // 静态不能直接访问非静态【重点】
//        System.out.println(num); // 错误写法!

        // 静态方法中不能使用this关键字。
//        System.out.println(this); // 错误写法!
    }

}

静态代码块的格式是:

public class 类名称 {
static {
// 静态代码块的内容
}
}

特点:当第一次用到本类时,静态代码块执行唯一的一次。
静态内容总是优先于非静态,所以静态代码块比构造方法先执行。

静态代码块的典型用途:
用来一次性地对静态成员变量进行赋值。

public static void main(String[] args) {
        Person one = new Person();
        Person two = new Person();
    }
public class Person {

    static {
        System.out.println("静态代码块执行!");
    }

    public Person() {
        System.out.println("构造方法执行!");
    }
 }
7、Arrays

java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。

public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1, 元素2, 元素3…])
public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。

备注:

  1. 如果是数值,sort默认按照升序从小到大
  2. 如果是字符串,sort默认按照字母升序
  3. 如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。
public static void main(String[] args) {
        int[] intArray = {10, 20, 30};
        // 将int[]数组按照默认格式变成字符串
        String intStr = Arrays.toString(intArray);
        System.out.println(intStr); // [10, 20, 30]

        int[] array1 = {2, 1, 3, 10, 6};
        Arrays.sort(array1);
        System.out.println(Arrays.toString(array1)); // [1, 2, 3, 6, 10]

        String[] array2 = {"bbb", "aaa", "ccc"};
        Arrays.sort(array2);
        System.out.println(Arrays.toString(array2)); // [aaa, bbb, ccc]
    }
8、Math类

java.util.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学运算相关的操作。

public static double abs(double num):获取绝对值。有多种重载。
public static double ceil(double num):向上取整。
public static double floor(double num):向下取整。
public static long round(double num):四舍五入。

Math.PI代表近似的圆周率常量(double)。

public static void main(String[] args) {
        //获取绝对值
        System.out.println(Math.abs(-3.14));

        //向上取整
        System.out.println(Math.ceil(4.2));

        //向下取整
        System.out.println(Math.floor(4.9));

        //四舍五入
        System.out.println(Math.round(4.51));
    }

九、继承

面向对象三大特征:封装、继承、多态。

继承是多态的前提,如果没有继承,就没有多态。

主要解决的问题:共性抽取

特点:1、子类可以拥有父类的可继承类容

​ 2、子类还可以拥有自己的专有类容


在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。
例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。

定义父类的格式:(一个普通的类定义)
public class 父类名称 {
// …


在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:

直接通过子类对象访问成员变量:
等号左边是谁,就优先用谁,没有则向上找。
间接通过成员方法访问成员变量:
该方法属于谁,就优先用谁,没有则向上找。


局部变量: 直接写成员变量名
本类的成员变量: this.成员变量名
父类的成员变量: super.成员变量名


在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写。
重载(Overload):方法的名称一样,参数列表【不一样】。

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

1、方法的覆盖重写

方法覆盖重写的注意事项:

  1. 必须保证父子类之间方法的名称相同,参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

  2. 子类方法的返回值必须【小于等于】父类方法的返回值范围。
    小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

  3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > (default) > private
    备注:(default)不是关键字default,而是什么都不写,留空。

public class NewPhone extends Phone {

    @Override
    public void show() {
        super.show(); // 把父类的show方法拿过来重复利用
        // 自己子类再来添加更多内容
        System.out.println("显示姓名");
        System.out.println("显示头像");
    }

继承关系中,父子类构造方法的访问特点:

  1. 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造。
  2. 子类构造可以通过super关键字来调用父类重载构造。
  3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。
2、super

super关键字的用法有三种:

  1. 在子类的成员方法中,访问父类的成员变量。
  2. 在子类的成员方法中,访问父类的成员方法。
  3. 在子类的构造方法中,访问父类的构造方法。
3、this

super关键字用来访问父类内容,而this关键字用来访问本类内容。用法也有三种:

  1. 在本类的成员方法中,访问本类的成员变量。
  2. 在本类的成员方法中,访问本类的另一个成员方法。
  3. 在本类的构造方法中,访问本类的另一个构造方法。
    在第三种用法当中要注意:
    A. this(…)调用也必须是构造方法的第一个语句,唯一一个。
    B. super和this两种构造调用,不能同时使用。
public class Zi extends Fu {

    int num = 20;

    public Zi() {
//        super(); // 这一行不再赠送
        this(123); // 本类的无参构造,调用本类的有参构造
//        this(1, 2); // 错误写法!
    }

    public Zi(int n) {
        this(1, 2);
    }

    public Zi(int n, int m) {
    }

    public void showNum() {
        int num = 10;
        System.out.println(num); // 局部变量
        System.out.println(this.num); // 本类中的成员变量
        System.out.println(super.num); // 父类中的成员变量
    }

    public void methodA() {
        System.out.println("AAA");
    }

    public void methodB() {
        this.methodA();
        System.out.println("BBB");
    }

4、继承的三个特点

Java语言是单继承的。

一个类的直接父类只能有一个。

Java语言可以多级继承

我有一个父亲,我父亲还有一个父亲,也就是爷爷。

一个类的直接父类是唯一的,但是一个父类可以拥有很多个子类。

5、抽象方法

如果父类的方法不确定如何进行{}方法体的实现,那么这应该是一个抽象方法


抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

如何使用抽象类和抽象方法:

  1. 不能直接创建new抽象类对象。
  2. 必须用一个子类来继承抽象父类。
  3. 子类必须覆盖重写抽象父类当中所有的抽象方法。
    覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
  4. 创建子类对象进行使用。
public abstract class Animal {

    public abstract void eat();

    public void normalMethod(){

    }
}
public class Cat extends Animal{

    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

一个抽象类不一定含有抽象方法,
只要保证抽象方法所在的类是抽象类,即可。

这样没有抽象方法的抽象类,也不能直接创建对象,在一些特殊场景下有用途。

十、接口

接口就是多个类的公共规范。
接口是一种引用数据类型,最重要的内容就是其中的:抽象方法。

如何定义一个接口的格式:
public interface 接口名称 {
// 接口内容
}

备注:换成了关键字interface之后,编译生成的字节码文件仍然是:.java --> .class。

如果是Java 7,那么接口中可以包含的内容有:

  1. 常量
  2. 抽象方法

如果是Java 8,还可以额外包含有:
3. 默认方法
4. 静态方法

如果是Java 9,还可以额外包含有:
5. 私有方法

接口使用步骤:

  1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口。
    格式:
    public class 实现类名称 implements 接口名称 {
    // …
    }
  2. 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
    实现:去掉abstract关键字,加上方法体大括号。
  3. 创建实现类的对象,进行使用。

注意事项:
如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。


在任何版本的Java中,接口都能定义抽象方法。
格式:
public abstract 返回值类型 方法名称(参数列表);

注意事项:

  1. 接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
  2. 这两个关键字修饰符,可以选择性地省略。(今天刚学,所以不推荐。)
  3. 方法的三要素,可以随意定义。
public interface MyInterfaceAbstract {

    // 这是一个抽象方法
    public abstract void methodAbs1();

    // 这也是抽象方法
    abstract void methodAbs2();

    // 这也是抽象方法
    public void methodAbs3();

    // 这也是抽象方法
    void methodAbs4();

}

从Java 8开始,接口里允许定义默认方法。
格式:
public default 返回值类型 方法名称(参数列表) {
方法体
}

备注:接口当中的默认方法,可以解决接口升级的问题。


  1. 接口的默认方法,可以通过接口实现类对象,直接调用。
  2. 接口的默认方法,也可以被接口实现类进行覆盖重写。

从Java 8开始,接口当中允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表) {
方法体
}
提示:就是将abstract或者default换成static即可,带上方法体。


问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
但是这个共有方法不应该让实现类使用,应该是私有化的。

解决方案:
从Java 9开始,接口当中允许定义私有方法。

  1. 普通私有方法,解决多个默认方法之间重复代码问题
    格式:
    private 返回值类型 方法名称(参数列表) {
    方法体
    }

  2. 静态私有方法,解决多个静态方法之间重复代码问题
    格式:
    private static 返回值类型 方法名称(参数列表) {
    方法体

 public default void methodDefault1() {
        System.out.println("默认方法1");
        methodCommon();
    }

    public default void methodDefault2() {
        System.out.println("默认方法2");
        methodCommon();
    }

    private void methodCommon() {
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }

接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。
格式:
public static final 数据类型 常量名称 = 数据值;
备注:
一旦使用final关键字进行修饰,说明不可改变。

注意事项:

  1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
  2. 接口当中的常量,必须进行赋值;不能不赋值。
  3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
public interface MyInterfaceConst {
    // 这其实就是一个常量,一旦赋值,不可以修改
    public static final int NUM_OF_MY_CLASS = 12;
}

使用接口的时候,需要注意:

  1. 接口是没有静态代码块或者构造方法的。
  2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
    格式:
    public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆盖重写所有抽象方法
    }
  3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
  4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
  5. 如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
  6. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

1、多态性

extends继承或者implements实现,是多态性的前提

erfaceAbstract {

// 这是一个抽象方法
public abstract void methodAbs1();

// 这也是抽象方法
abstract void methodAbs2();

// 这也是抽象方法
public void methodAbs3();

// 这也是抽象方法
void methodAbs4();

}


---

从Java 8开始,接口里允许定义默认方法。
格式:
public default 返回值类型 方法名称(参数列表) {
    方法体
}

备注:接口当中的默认方法,可以解决接口升级的问题。

---

1. 接口的默认方法,可以通过接口实现类对象,直接调用。
2. 接口的默认方法,也可以被接口实现类进行覆盖重写。

---

从Java 8开始,接口当中允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表) {
    方法体
}
提示:就是将abstract或者default换成static即可,带上方法体。

---

问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题。
但是这个共有方法不应该让实现类使用,应该是私有化的。

解决方案:
从Java 9开始,接口当中允许定义私有方法。
1. 普通私有方法,解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表) {
    方法体
}

2. 静态私有方法,解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表) {
    方法体

```java
 public default void methodDefault1() {
        System.out.println("默认方法1");
        methodCommon();
    }

    public default void methodDefault2() {
        System.out.println("默认方法2");
        methodCommon();
    }

    private void methodCommon() {
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }

接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。
格式:
public static final 数据类型 常量名称 = 数据值;
备注:
一旦使用final关键字进行修饰,说明不可改变。

注意事项:

  1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
  2. 接口当中的常量,必须进行赋值;不能不赋值。
  3. 接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)
public interface MyInterfaceConst {
    // 这其实就是一个常量,一旦赋值,不可以修改
    public static final int NUM_OF_MY_CLASS = 12;
}

使用接口的时候,需要注意:

  1. 接口是没有静态代码块或者构造方法的。
  2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
    格式:
    public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆盖重写所有抽象方法
    }
  3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
  4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
  5. 如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
  6. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

Final关键字

当Final关键字用来修饰一个类的时候,格式:
public final class 类名称{
}
final类不能作为父类,abstract与final不能同时使用,因为abstract必须覆盖冲重写。

1、一但使用final来修饰局部变量,那么这个变量就不能就行更改

 final int num2 = 200;

对于基本类型来说,是数据不可变
对于引用类型来说,是地址值不可变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值