Java基础知识(建议收藏)

该篇为学习java整理的有关基础知识的笔记。
大部分源自于以下链接P1~P214:
https://www.bilibili.com/video/BV1uJ411k7wy?p=1
感谢此老师倾囊相授
下一篇Java进阶知识01链接:https://blog.csdn.net/weixin_45860674/article/details/119650957

1 MS-DOS命令提示符

2 IDEA快捷键

3 JAVA开发环境

3.1 JVM

JVM(Java Virtual Machine ):Java虚拟机,简称JVM,是运行所有Java程序的假想计算机,是Java程序的 运行环境,是Java 最具吸引力的特性之一。我们编写的Java代码,都运行在 JVM 之上。

跨平台:任何软件的运行,都必须要运行在操作系统之上,而我们用Java编写的软件可以运行在任何的操作系 统上,这个特性称为Java语言的跨平台特性。该特性是由JVM实现的,我们编写的程序运行在JVM上,而JVM 运行在操作系统上。

如图,JAVA虚拟机本身不具备跨平台的功能,每个操作系统下都有不同版本的虚拟机

3.2 JRE和JDK

JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。

JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。

我们想要运行一个已有的Java程序,那么只需安装 JRE 即可。

我们想要开发一个全新的Java程序,那么必须安装 JDK 。

三者关系: JDK > JRE > JVM

4 JAVA基本知识

4.1 数据类型分类

Java的数据类型分为两大类:

基本数据类型:包括 整数 、 浮点数 、 字符 、 布尔 。

引用数据类型:包括 类 、 数组 、 接口 。

四类八种基本数据类型:

4.2 数据类型转换

范围小的类型向范围大的类型提升

byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double

4.3 JAVA虚拟机内存划分

5 数组

数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。

5.1 格式

  1. 数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];
  2. 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3…};
  3. 数据类型[] 数组名 = {元素1,元素2,元素3…} ;

5.2 注意事项

  1. 不能越界,否则报错
  2. 数组空指针异常

5.3 数组作为方法参数和返回值

  1. 数组作为方法参数传递,传递的参数是数组内存的地址。
  2. 数组作为方法的返回值,返回的是数组的内存地址

6 类

  1. 定义类:就是定义类的成员,包括成员变量和成员方法。
  2. 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。
  3. 成员方法:和以前定义方法几乎是一样的。只不过把static去掉。

6.1 成员变量默认值

6.2 一个对象的内存图

6.3 两个对象使用同一个方法内存图

6.4 两个引用指向同一个对象的内存图

6.5 成员变量和局部变量区别

在类中的位置不同

  1. 成员变量:类中,方法外
  2. 局部变量:方法中或者方法声明上(形式参数)

作用范围不一样

  1. 成员变量:类中
  2. 局部变量:方法中

初始化值的不同

  1. 成员变量:有默认值
  2. 局部变量:没有默认值。必须先定义,赋值,最后使用

在内存中的位置不同

  1. 成员变量:堆内存
  2. 局部变量:栈内存

生命周期不同 了解

  1. 成员变量:随着对象的创建而存在,随着对象的消失而消失
  2. 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

7 封装

将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

7.1 步骤

  1. 使用 private 关键字来修饰成员变量。 被private修饰后的成员变量和成员方法,只在本类中才能访问。
  2. 对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。

7.2 封装优化

7.2.1 this

this代表所在类的当前对象的引用(地址值),即对象自己的引用。

记住 :方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁。

7.2.2 构造方法

当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。

无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法, 一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。

一个例子:

public class Student {
    private String name;
    private int age;
    // 无参数构造方法
    public Student() {}
    // 有参数构造方法
    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }
}

注意事项:

  1. 如果你不提供构造方法,系统会给出无参数构造方法。
  2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
  3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。

7.3 标准规范JavaBean

public class ClassName{
    //成员变量
    //构造方法
    //无参构造方法【必须】
    //有参构造方法【建议】
    //成员方法
    //getXxx()
    //setXxx()
}

8 API

API(Application Programming Interface),应用程序编程接口

9 Scanner类

一个可以解析基本类型和字符串的简单文本扫描器。 例如,以下代码使用户能够从 System.in 中读取一个数。

System.in 系统输入指的是通过键盘录入数据。

9.1 使用步骤

导包

import java.util.Scanner;

创建对象

Scanner sc = new Scanner(System.in);

调用方法

int i = sc.nextInt(); // 接收一个键盘录入的整数

10 匿名对象

创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。

注意:

  1. 创建匿名对象直接调用方法,没有变量名。
  2. 一旦调用两次方法,就是创建了两个对象,造成浪费。
  3. 匿名对象可以作为方法的参数返回值

11 Random类

此类的实例用于生成伪随机数。

11.1 使用步骤

导包

import java.util.Random;

创建对象

Random r = new Random();

11.2 成员方法

public int nextInt(int n) :返回一个伪随机数,范围在 0 (包括)和 指定值 n (不包括)之间的 int 值。

12 ArrayList类

数组的长度是固定的,无法适应数据变化的需 求。为了解决这个问题,Java提供了另一个容器 java.util.ArrayList 集合类,让我们可以更便捷的存储和操作对象数据。

java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素。此类提供一些方法来操作内部存储 的元素。 ArrayList 中可不断添加元素,其大小也自动增长。

12.1 使用方法

导包

import java.util.ArrayList;

创建对象

ArrayList list = new ArrayList<>();

12.2 成员方法

  1. public boolean add(E e) :将指定的元素添加到此集合的尾部。
  2. public E remove(int index) :移除此集合中指定位置上的元素。返回被删除的元素。
  3. public E get(int index) :返回此集合中指定位置上的元素。返回获取的元素。
  4. public int size() :返回此集合中的元素数。遍历集合时,可以控制索引范围,防止越界。

12.3 如何存储基本数据类型

ArrayList对象不能存储基本类型,只能存储引用类型的数据。类似 不能写,但是存储基本数据类型对应的 包装类型是可以的。

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

13 String类

13.1 特点

  1. 字符串不变:字符串的值在创建后不能被更改。
  2. 因为String对象是不可变的,所以它们可以被共享。
  3. “abc” 等效于 char[] data={ ‘a’ , ‘b’ , ‘c’ } 。

13.2 构造方法

  1. public String() :初始化新创建的 String对象,以使其表示空字符序列。
  2. public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  3. public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的 String。

13.3 常用方法

以下两种都返回布尔值:

  1. public boolean equals (Object anObject) :将此字符串与指定对象进行比较。
  2. public boolean equalsIgnoreCase (String anotherString) :将此字符串与指定对象进行比较,忽略大小写。

*equals方法:推荐常量写前面,变量写后面,例如:“abc”.equals(str1) ,因为str1为空倒过来回报错

13.4 常用功能方法

  1. public int length () :返回此字符串的长度。
  2. public String concat (String str) :将指定的字符串连接到该字符串的末尾。
  3. public char charAt (int index) :返回指定索引处的 char值。
  4. public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。
  5. public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符 串结尾。
  6. public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到 endIndex截取字符串。含beginIndex,不含endIndex。

13.5 转换功能方法

  1. public char[] toCharArray () :将此字符串转换为新的字符数组。
  2. public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
  3. public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使 用replacement字符串替换。

13.6 分割功能方法

public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。

*split方法:如果用.切分则需要写 " \ \ ."

13.7 内存图

1、对于引用类型来说,==进行的是地址值的比较。
2、双引号直接写的字符串在常量池当中,new的不在池当中。

14 Static关键字

推荐用类名调用静态方法,不推荐用对象名调用

14.1 类变量(一个例子)

当 static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改 该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作

public class Student {
    private String name;
    private int age;
    // 学生的id
    private int sid;
    // 类变量,记录学生数量,分配学号
    public static int numberOfStudent = 0;
    public Student(String name, int age){
        this.name = name;
        this.age = age;
        // 通过 numberOfStudent 给学生分配学号
        this.sid = ++numberOfStudent;
    }
    // 打印属性值
    public void show() {
        System.out.println("Student : name=" + name + ", age=" + age + ", sid=" + sid );
    }
}
public class StuDemo {
    public static void main(String[] args) {
        Student s1 = new Student("张三", 23);
        Student s2 = new Student("李四", 24);
        Student s3 = new Student("王五", 25);
        Student s4 = new Student("赵六", 26);
        s1.show(); // Student : name=张三, age=23, sid=1
        s2.show(); // Student : name=李四, age=24, sid=2
        s3.show(); // Student : name=王五, age=25, sid=3
        s4.show(); // Student : name=赵六, age=26, sid=4
    }
}

14.2 静态方法

当 static 修饰成员方法时,该方法称为类方法 。静态方法在声明中有 static ,建议使用类名来调用,而不需要创建类的对象。调用方式非常简单。

注意事项:

  1. 静态方法可以直接访问类变量和静态方法
  2. 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。 静态方法只能访问静态成员。
  3. 静态方法中,不能使用this关键字。

14.3 内存图

静态代码块:

15 Array类

java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来 非常简单。

15.1 操作数组的方法

  1. public static String toString(int[] a) :返回指定数组内容的字符串表示形式。
  2. public static void sort(int[] a) :对指定的 int 型数组按数字升序进行排序。

16 Math类

java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具 类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。

16.1 基本运算方法

  1. public static double abs(double a) :返回 double 值的绝对值。
  2. public static double ceil(double a) :返回大于等于参数的最小的整数。
  3. public static double floor(double a) :返回小于等于参数最大的整数。
  4. public static long round(double a) :返回最接近参数的 long。(相当于四舍五入方法)

17 继承

直接通过子类对象访问成员变量(num):等号左边是谁,就优先用谁,没有则向上找。

间接通过成员方法访问成员变量(methodFu() methodZi()):该方法属于谁,就优先用谁,没有则向上找。

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

17.1 重写

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

重载(Overload):方法的名称一样,参数列表【不一样】。

Tips:重写的时候用上@Override 会有系统检查,避免小手一抖写错重写

注意事项:

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

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

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

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

17.2 父子类构造方法

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

  1. 子类构造方法当中有一个默认隐含的“super()"调用,所以一定是先调用的父类构造,后执行的子类构造。
  2. 子类构造可以通过super关键字来调用父类重载构造。
  3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。

总结:子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个.还必须是第一个。

17.3 super三种用法(访问父类)

  1. 在子类的成员方法中,访问父类的成员变量。
  2. 在子类的成员方法中,访问父类的成员方法。
  3. 在子类的构造方法中,访问父类的构造方法。public Zi(){super();}

17.4 this三种方法(访问本类)

  1. 在本类的成员方法中,访问本类的成员变量。
  2. 在本类的成员方法中,访问本类的另—个成员方法。
  3. 在本类的构造方法中,访问本类的另一个构造方法。

在第三种用法当中要注意:

A. this ( …)调用也必须是构造方法的第一个语句,唯一一个。

B.super和this两种构造调用,不能同时使用。

17.5 super和this内存图

18 抽象类

抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。

抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

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

1.不能直接创建new抽象类对象。

2.必须用一个子类来继承抽象父类。

3.子类必须覆盖重写抽象父类当中所有的抽象方法。

覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。

4.创建子类对象进行使用。

19 微信发红包案例(⭐)

用户类

public class User {
    // 成员变量
    private String username; // 用户名
    private double leftMoney; // 余额
    // 构造方法
    public User() { 
    }
    
    public User(String username, double leftMoney) {
        this.username = username;
        this.leftMoney = leftMoney;
    }
    
    // get/set方法
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public double getLeftMoney() {
        return leftMoney;
    }
    public void setLeftMoney(double leftMoney) {
        this.leftMoney = leftMoney;
    }
    
    // 展示信息的方法
    public void show() {
        System.out.println("用户名:"+ username +" , 余额为:" + leftMoney + "元");
    }
}

群主类

public class QunZhu extends User {
    // 添加构造方法
    public QunZhu() {
    }
    public QunZhu(String username, double leftMoney) {
        // 通过super 调用父类构造方法
        super(username, leftMoney);
    }
    /*
    群主发红包,就是把一个整数的金额,分层若干等份。
    1.获取群主余额,是否够发红包.
    不能则返回null,并提示.
    能则继续.
    2.修改群主余额.
    3.拆分红包.
    3.1.如果能整除,那么就平均分。
    3.2.如果不能整除,那么就把余数分给最后一份。
    */
    public ArrayList<Double> send(int money, int count) {
        // 获取群主余额
      	double leftMoney = getLeftMoney();
        if(money > leftMoney) {
            return null;
        }
        // 修改群主余额的
        setLeftMoney(leftMoney ‐ money);
        // 创建一个集合,保存等份金额
        ArrayList<Double> list = new ArrayList<>();
        // 扩大100倍,相当于折算成'分'为单位,避免小数运算损失精度的问题
        money = money * 100;
        // 每份的金额
        int m = money / count;
        // 不能整除的余数
        int l = money % count;
        // 无论是否整除,n‐1份,都是每份的等额金额
        for (int i = 0; i < count ‐ 1; i++) {
            // 缩小100倍,折算成 '元'
            list.add(m / 100.0);
        }
        // 判断是否整除
        if (l == 0) {
            // 能整除, 最后一份金额,与之前每份金额一致
            list.add(m / 100.0);
        } else {
            // 不能整除, 最后一份的金额,是之前每份金额+余数金额
            list.add((m + l) / 100.00);
        }
        // 返回集合
        return list;
    }
}

成员类

public class Member extends User {
    public Member() {
    }
    public Member(String username, double leftMoney) {
        super(username, leftMoney);
    }
    // 打开红包,就是从集合中,随机取出一份,保存到自己的余额中
    public void openHongbao(ArrayList<Double> list) {
        // 创建Random对象
        Random r = new Random();
        // 随机生成一个角标
        int index = r.nextInt(list.size());
        // 移除一个金额
        Double money = list.remove(index);
        // 直接调用父类方法,设置到余额
        setLeftMoney( money );
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        // 创建一个群主对象
        QunZhu qz = new QunZhu("群主" , 200);
        // 创建一个键盘录入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入金额:");
        int money = sc.nextInt();
        System.out.println("请输入个数:");
        int count = sc.nextInt();
        // 发送红包
        ArrayList<Double> sendList = s.send(money,count);
        // 判断,如果余额不足
        if(sendList == null){
            System.out.println(" 余额不足...");
            return;
        }
        // 创建三个成员
        Member m = new Member();
        Member m2 = new Member();
        Member m3 = new Member();
        // 打开红包
        m.openHongbao(sendList);
        m2.openHongbao(sendList);
        m3.openHongbao(sendList);
        // 展示信息
        qz.show();
        m.show();
        m2.show();
        m3.show();
    }
}

20 接口

20.1 抽象方法abstract

一定要覆盖重写,否则报错。

通过实现类的对象来调用。

不用写方法体。

20.2 默认方法default

假设有一个很大很大的项目,一个接口被很多很多的类所实现,大家都平安无事平稳地运行着。突然有一天,出现了一个小小地问题,或者说有一个更好的优化方案,需要在这些实现类去增加。在默认方法出现之前,只有抽象方法,且需要在实现类中给出具体定义才能操作,那岂不是只能两眼一闭,直接从早干到晚地添加啦。
但是,默认方法地出现允许在接口中给出方法的具体实现,且实现类中能够自动实现默认方法,我只需要将这个优化放在接口的默认方法里面,就能完成对所有实现类的优化啦。

可覆盖重写也可以不, 二选一。

但是只能通过实现类的对象来调用。

要写方法体。

20.3 静态方法static

在没有新增静态方法之前,我们如果想让一些固定的操作在接口中出现,就必须定义一个和接口配套的实现类。而接口中静态方法的出现,可以直接通过接口调用静态方法。

就很直接地在接口中定义静态方法,且可以被接口直接调用,不需要再定义与其配套的实现类,多舒服哦。

不能在实现类里重写静态方法。

不能通过接口实现类的对象来调用接口当中的静态方法。 一定要通过接口名称直接调用其中的静态方法。

要写方法体。

20.4 私有方法private

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

1.普通私有方法,解决多个默认方法之间重复代码问题格式:

private 返回值类型 方法名称(参数列表){
    方法体
}

2.静态私有方法,解决多个静态方法之间重复代码问题格式:

private static 返回值类型 方法名称(参数列表){
	方法体
}

20.5 接口常量

接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。

从效果上看,这其实就是接口的【常量】。

格式:

public static final 数据类型常量名称 = 数据值 ;

备注:

—旦使用final关键字进行修饰,说明不可改变。

注意事项:
1.接口当中的常量,可以省略public static final,注意:不写也照样是这样。

2.接口当中的常量,必须进行赋值;不能不赋值。

3.接口中常量的名称,使用完全大写的字母,用下划线进行分隔。(推荐命名规则)

20.6 接口注意事项

1.接口是没有静态代码块或者构造方法的。

2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。

格式:

public class MyInterfaceImpl implements MyInterfaceAMyInterfaceB {/覆盖重写所有抽象方法
}

3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。

4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。

5.如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。

6.一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

20.7 接口多继承

1.类与类之间是单继承的。直接父类只有一个。

2.类与接口之间是多实现的。一个类可以实现多个接口。

3.接口与接口之间是多继承的。

注意事项:

1、多个父接口当中的抽象方法如果重复,没关系。
2、多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写【而且带着default关键字】

子接口重写默认方法时,default关键字可以保留。

子类重写默认方法时,default关键字不可以保留。

21 多态性

21.1 成员方法

因为方法覆盖重写,所以调用的是重写后的Zi的method(),此时方法看等号右边。

编译看左边,运行看右边。

Fu obj = new Zi();
obj.method();
//子

21.2 成员变量

不会覆盖重写,所以要看等号左边是谁,优先用谁,没有则向上找。

编译看左边,运行还看左边。

Fu obj = new Zi();
sout(obj.num);
//父

多态性的优势:https://www.cnblogs.com/lv-suma/p/12842575.html

由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当 然可以把Cat对象和Dog对象,传递给方法。

当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致, 所以showAnimalEat完全可以替代以上两方法。

不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用 showAnimalEat都可以完成。

所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。

21.3 对象向上转型

21.4 对象向下转型

向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

解决方案:用对象的向下转型还原。

21.5 instanceof

变量名 instanceof 数据类型

如果变量属于该数据类型,返回true。

如果变量不属于该数据类型,返回false。

22 笔记本电脑案例(⭐)

笔记本电脑(laptop)通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。

定义USB接口,具备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守 USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。

USB类

package cn.itcast.day08.demo06;

public interface USB {
    void open();
    void close();
}

键盘类

package cn.itcast.day08.demo06;

public class KeyBoard implements USB {
    @Override
    public void open() {
        System.out.println("键盘开启,绿灯闪一闪。");
    }

    @Override
    public void close() {
        System.out.println("键盘关闭,绿灯熄灭.");
    }

    public void click(){
        System.out.println("键盘敲击。");
    }
}

鼠标类

package cn.itcast.day08.demo06;

public class Mouse implements USB {
    @Override
    public void open() {
        System.out.println("鼠标开启,红灯闪一闪。");
    }

    @Override
    public void close() {
        System.out.println("鼠标关闭,红灯熄灭。");
    }
    public void click(){
        System.out.println("鼠标单击。");
    }
}

计算机类

package cn.itcast.day08.demo06;

public class Lap{
    public void powerOn(){
        System.out.println("开机!");
    }
    public void powerOff(){
        System.out.println("关机!");
    }

    public void useDevice(USB usb){
        //这里不能直接调用usb.click,必须向下转型
        if(usb!= null){
            usb.open();
            if(usb instanceof Mouse){
                Mouse m = (Mouse) usb;
                m.click();
            }else if(usb instanceof KeyBoard){
                KeyBoard k = (KeyBoard) usb;
                k.click();
            }
            usb.close();
        }
    }
}

测试类

package cn.itcast.day08.demo06;

public class Demo01 {
    public static void main(String[] args) {
        Lap lt = new Lap();
        lt.powerOn();
        USB u = new Mouse();
        lt.useDevice(u);

        KeyBoard kb = new KeyBoard();
        lt.useDevice(kb);//自动发生向上转型

        lt.powerOff();
    }
}

23 final

23.1 类

public final class 类名 {
}

查询API发现像 public final class String 、 public final class Math 、 public final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。

23.2 方法

修饰符 final 返回值类型 方法名(参数列表){
    //方法体
}

重写被 final 修饰的方法,编译时就会报错。

23.3 局部变量

21.3.1 基本类型

被final修饰后,只能赋值一次,不能再更改

变量当中的数据不可改变

21.3.2 引用类型

引用类型的局部变量,被final修饰后,只能指向一个对象 ,地址值不可改变,但是不影响对象内部的成员变量值的修改 。

23.4 成员变量

成员变量具有默认值所以用了final之后必须手动赋值,不会再给默认值。

对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。

必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。

被final修饰的常量名称,一般都有书写规范,所有字母都大写。

24 四种权限修饰符

public:公共的

protected:受保护的

default:默认的

private:私有的

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  1. 成员变量使用 private ,隐藏细节。
  2. 构造方法使用 public ,方便创建对象。
  3. 成员方法使用 public ,方便调用方法。

小贴士:不加权限修饰符,其访问能力与default修饰符相同

25 内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

访问特点:

  1. 内部类可以直接访问外部类的成员,包括私有成员。
  2. 外部类要访问内部类的成员,必须要建立内部类的对象。

访问方式:

  1. 间接方式:在外部类方法中,使用内部类,然后main只调用外部类的方法。
  2. 直接方式: 外部类名.内部类名 对象名 = new 外部类型().new 内部类型();

内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。

比如,Person$Heart.class

25.1 重名

外部类成员变量内部类成员变量内部类局部变量重名

25.2 局部内部类

25.2.1 定义

如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。

25.2.2 定义格式

只要之后在psvm中调用Outer.methodOuter()方法就行

25.2.3 局部内部类里的final

25.2.4 注意事项

25.3 匿名内部类

25.3.1 定义

是内部类的简化写法。它的本质是一 带具体实现的 父类或者父接口的 匿名的 子类对象。

25.3.2 定义格式

接口名称 对象名 = new 接口名称(){

​ //覆盖重写所有抽象方法

};

对格式"new 接口名称(){…}"进行解析:

1、new代表创建对象的动作

2、接口名称才是匿名内部类需要实现哪个接口

3、{……}这才是你们内部类的内容

25.3.3 注意

1.匿名内部类,在【创建对象】的时候,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。

2.匿名对象,在【调用方法】的时候,只能调用唯——次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。

3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】

26 引用类型用法总结

基本类型可以作为成员变量、作为方法的参数、作为方法的返回值,那么当然引用类 型也是可以的。

26.1 class作为成员变量

类作为成员变量时,对它进行赋值的操作,实际上,是赋给它该类的一个对象。

class Weapon {
    String name; // 武器名称
    int hurt; // 伤害值
}
class Role {
    int id;
    int blood;
    String name;
    // 添加武器属性
    Weapon wp;

    // 提供get/set方法
    public Weapon getWp() {
       return wp;
    }
    public void setWeapon(Weapon wp) {
        this.wp = wp;
    }

    // 攻击方法
    public void attack(){
        System.out.println("使用"+ wp.getName() +", 造成"+wp.getHurt()+"点伤害");
    }
}
public class Test {
    public static void main(String[] args) {
        // 创建Weapon 对象
        Weapon wp = new Weapon("屠龙刀" , 999999);
        // 创建Role 对象
        Role r = new Role();
        // 设置武器属性
        r.setWeapon(wp);
        // 攻击
        r.attack();
    }
}
输出结果:
使用屠龙刀,造成999999点伤害

26.2 interface作为成员变量

接口是对方法的封装,对应游戏当中,可以看作是扩展游戏角色的技能。所以,如果想扩展更强大技能,我们在 Role 中,可以增加接口作为成员变量,来设置不同的技能。

// 法术攻击
public interface FaShuSkill {
	public abstract void faShuAttack();
}
public class Role {
    FaShuSkill fs;
    public void setFaShuSkill(FaShuSkill fs) {
        this.fs = fs;
    }
    // 法术攻击
    public void faShuSkillAttack(){
        System.out.print("发动法术攻击:");
        fs.faShuAttack();
        System.out.println("攻击完毕");
    }
}
public class Test {
    public static void main(String[] args) {
        // 创建游戏角色
        Role role = new Role();
        // 设置角色法术技能
        role.setFaShuSkill(new FaShuSkill() {
            @Override
            public void faShuAttack() {
                System.out.println("纵横天下");
            }
        });
        // 发动法术攻击
        role.faShuSkillAttack();
        // 更换技能
        role.setFaShuSkill(new FaShuSkill() {
            @Override
            public void faShuAttack() {
                System.out.println("逆转乾坤");
            }
        });
        // 发动法术攻击
        role.faShuSkillAttack();
    }
}
输出结果:
发动法术攻击:纵横天下
攻击完毕
发动法术攻击:逆转乾坤
攻击完毕

我们使用一个接口,作为成员变量,以便随时更换技能,这样的设计更为灵活,增强了程序的扩展性。 接口作为成员变量时,对它进行赋值的操作,实际上,是赋给它该接口的一个子类对象。

26.3 interface作为方法参数和返回值类型

当接口作为方法的参数时,需要传递什么呢?当接口作为方法的返回值类型时,需要返回什么呢?对,其实都是它的 子类对象。 ArrayList 类我们并不陌生,查看API我们发现,实际上,它是 java.util.List 接口的实现类。所 以,当我们看见 List 接口作为参数或者返回值类型时,当然可以将 ArrayList 的对象进行传递或返回。

27 拼手气红包案例(⭐)

接口

public interface OpenMode {
/**
* @param totalMoney 总金额,单位是"分"。总金额为方便计算,已经转换为整数,单位为分。
* @param count 红包个数
* @return ArrayList<Integer> 元素为各个红包的金额值,所有元素的值累和等于总金额.
*
* 请将totalMoney,分成count分,保存到ArrayList<Integer>中,返回即可.
*/
public abstract ArrayList<Integer> divide(int totalMoney, int count);
}

普通红包

public class RedPacketTest {
    public static void main(String[] args) {
        // 创建红包对象
        RedPacket rp = new RedPacket("大红包");
        // 设置群主名称
        rp.setOwnerName("我是群大大");
        // 设置红包类型
        rp.setOpenMode(new Common()); // 普通红包
    }
}

public class Common implements OpenMode {
    @Override
    public ArrayList<Integer> divide(int totalMoney, int count) {
        // 创建保存各个红包金额的集合
        ArrayList<Integer> list = new ArrayList<>();
        // 定义循环次数,总个数‐1次
        int time = count ‐ 1;
        // 一次计算,生成平均金额
        int money = totalMoney / count;
        // 循环分配
        for (int i = 0; i < time; i++) {
            // 添加到集合中
            list.add(money);
            // 总金额扣除已分配金额
            totalMoney ‐= money;
        }
        // 剩余的金额,为最后一个红包
        list.add(totalMoney);
        System.out.println("普通红包金额:" + list);
        // 返回集合
        return list;
    }
}

手气红包

public class RedPacketTest {
    public static void main(String[] args) {
        // 创建红包对象
        RedPacket rp = new RedPacket("大红包");
        // 设置群主名称
        rp.setOwnerName("我是群大大");
        // 设置红包类型,二选一
        // rp.setOpenMode(new Common()); // 普通红包
        rp.setOpenMode(new Lucky()); // 手气红包

    }
}
public class Lucky implements OpenMode {
    @Override
    public ArrayList<Integer> divide(int totalMoney, int count) {
        // 创建保存各个红包金额的集合
        ArrayList<Integer> list = new ArrayList<>();
        // 定义循环次数,总个数‐1次
        int time = count ‐ 1;
        // 创建随机数对象
        Random random = new Random();
        // 循环分配
        for (int i = 0; i < time; i++) {
            /*
            * 每次重新计算,生成随机金额
            * 随机范围: totalMoney / count * 2,totalMoney不断的减少,
            * count也不断的减少,所以这是一个可变化的范围.
            */
            int money = random.nextInt(totalMoney / count * 2) + 1;
            // 金额添加到集合
            list.add(money);
            // 总金额扣除已分配金额
            totalMoney ‐= money;
            // 红包个数‐1
            count‐‐;
        }
        // 剩余的金额,为最后一个红包
        list.add(totalMoney);
        return list;
    }
}

基础篇结束啦!

下一篇进阶知识01请查阅:
https://blog.csdn.net/weixin_45860674/article/details/119650957

  • 233
    点赞
  • 1611
    收藏
    觉得还不错? 一键收藏
  • 40
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值