Java基础篇面向对象总结

面向对象知识点汇总

  • 1.必备基础知识
    • 1.1"理解万事万物皆对象"
    • 1.2、基本类型和引用类型
    • 1.3匿名对象的使用
    • 1.4方法重载loading....
    • 1.5方法重写
      • 1.5.1 方法重载与方法重写的区别:
    • 1.6可变个数的形参
    • 1.7递归地使用
  • 2.进阶基础知识
    • 2.1面向对象的特征
      • 2.1.1面向对象的特征之一封装和隐藏
        • 2.1.1.1知识拓展之四种权限修饰符
      • 2.1.2面向对象的特征之二继承
      • 2.1.3面向对象的特征之三多态
    • 2.2类的结构
      • 2.2.1类的结构之一属性
      • 2.2.2类的结构之二方法
      • 2.2.3类的结构之三构造器
      • 2.2.4类的结构之四代码块
      • 2.2.5类的结构之五内部类(了解)
    • 2.3关键字的使用
      • 2.3.1this关键字
      • 2.3.2package关键字
      • 2.3.3import关键字
      • 2.3.4super关键字
      • 2.3.5instanceof关键字
      • 2.3.6static关键字
      • 2.3.7***abstract关键字
      • 2.3.8***Interface关键字
    • 2.4零散知识点总结
      • 2.4.1equals()方法的使用
        • 2.4.1.1"=="和equals之间的区别
      • 2.4.2toString()方法的使用
    • 2.4.3 单例模式

1.必备基础知识

1.1"理解万事万物皆对象"

     1.在Java语言范畴中,我们都将 功能、结构等封装到类中,通过类的实例化,来调用具体的结构功能。

     2.涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。

1.2、基本类型和引用类型

概述:
     1.基本类型:它的值就是一个数字,一个字符或一个布尔值。 赋值时保存的是变量----保存的数值----
     2.引用类型:是一个对象类型,它的值是指向内存空间的引用,就是地址,所指向的内存中保存着变量所表示的一个值或一组值 引用类型的变量只能存储两类值:null或者地址值(含变量的类型)
赋值时保存的是----变量的地址----
     3.数组直接赋值方法:
样例:int[] arr = new int[]{12,456,87,-45,56,45,563,43,452,651};
4.值传递机制:

使用样例:

4.1如果参数是基本数据类型,此时实参赋给形参的是—实参真实存储的数据值

基本数据数据类型
ValueTransferTest.java

    public class ValueTransferTest {
    public static void main(String[] args) {

        int m = 10;
        int n = 20;
        System.out.println("交换数据前:");
        System.out.println("m = :" + m + ",n = :" + n);

        System.out.println("交换数据后:");
        ValueTransferTest test = new ValueTransferTest();
        test.swap(m,n);
        System.out.println("m = :" + m + ",n = :" + n);//10,20


    }

    public void swap(int m, int n) {
        int temp = m;
        m = n;
        n = temp;//20,10
    }
}

4.2 如果参数是引用数据类型,此时实参赋给形参的是—实参存储数据的地址值(含变量类型的地址值)

ValueTransferTest1.java

 public class ValueTransferTest1 {
    public static void main(String[] args) {

        Data data = new Data();

        data.m = 10;
        data.n = 20;
        System.out.println("交换数据前:");
        System.out.println("m = "+data.m+",n = :"+data.n);

        ValueTransferTest1 test1 = new ValueTransferTest1();
        test1.swap(data);
        System.out.println("交换数据后:");
        System.out.println("m = "+data.m+",n = :"+data.n);


    }

    public void swap(Data data){
        int temp = data.m;
        data.m = data.n;
        data.n = temp;
    }
}
class Data{
    int m;
    int n;
}

2.4.1数组使用样例:

//数组排序
    public void sort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                /*if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }*/
                swap(arr,j,j+1);
            }
        }
    }


    
//数组中两个数值的交换
    public void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

1.3匿名对象的使用

InstanceTest.java
概述:

1.理解:在创建对象的时候,没有给它名字,直接调用例如:new Phone().sendEmail();

2.匿名对象只能使用一次

使用样例:

public class InstanceTest {
    public static void main(String[] args) {

        //赋予名字对象的使用
        Phone p = new Phone();

        p.price = 20.0;
        p.shoePrice();
        p.sendEmail();
        p.playGame();

        //只是创建了匿名对象
        new Phone().price=1999;
        new Phone().shoePrice();//0.0

        //匿名对象的使用
        Phonemall mall = new Phonemall();
        mall.show(new Phone());//在这种情况下,匿名对象可以多次使用
    }
}

//mall:商场
class Phonemall{
    public void show(Phone phone){
        phone.sendEmail();
        phone.playGame();
    }
}

class Phone{
    //成员变量
    double price;//手机价格

    //成员方法
    public void sendEmail(){
        System.out.println("发送邮件");
    }

    public void playGame(){
        System.out.println("玩游戏");
    }

    public void shoePrice(){
        System.out.println("手机的价格是:"+price);
    }
}

1.4方法重载loading…

OverLoadTest.java
概述

      1.在同一个类中,允许存在一个以上同名的方法,只要他们的参数个数或者参数类型不同即可。

使用样例

      2.举例
实现数组反转的重载:reverse(int[] arr) / reverse(double[] arr)
     3. “两同一不同” 两同:同一个类中,相同方法名
不同:参数列表,参数个数不同,参数类型

     4.与方法的权限修饰符,返回值类型,形参变量,方法体没有关系;
     5.再通过对象调用方法时,如何确定使用的方法:
方法名------>参数列表

/*
* 1.方法重载
* 2.方法重载的要点:----------同一个类,同一个名,形参列表不同----------
* */
public class OverLoadTest {

    public void getSum(int i, int j) {
        System.out.println(i + j);
    }

    public void getSum(double i, double j) {
        System.out.println(i + j);
    }

    public void getSum(String s, int j) {
        System.out.println(s + j);
    }

    public void getSum(int j, String s) {
        System.out.println(s + j);
    }
}

1.5方法重写

1.概念:

     1.1重写:子类继承父类以后,可以对父类中同名同参数的方法,进行重写覆盖
    1.2重写的实际意义在于:继承父类以后发现父类的方法不是自己想要执行的,所以子类就重新安排方法的内容

2.总结性内容:

     2.1应用:重写以后,当创建子类对象以后,通过子类对象调用父类同名的方法以后,实际执行的是子类重写父类的方法

    2.2重写的规定:
    方法的声明:
    权限修饰符 返回值类型 方法名(形参列表)throws 异常的类型{
           //方法体
       }

    在实际的使用过程中,只需要将父类的权限修饰符 返回值类型 方法名(形参列表)这一部分直接粘贴过来就可以,没有那么多的规矩,下面的知识点只是帮助理解的内容:

    约定的俗称:子类中的叫重写的方法,父类中的叫被重写的方法
1.子类的重写方法和父类的被重写方法的方法名和形参列表要相同
2.子类的权限修饰符不能小于父类的权限修饰符类型:private–>default(缺省)–>protected–>public
–>特殊情况:父类的权限修饰符类型是private时,子类不能够重写,子类可以自己写一样的但是不认为是重写
3.:返回值类型:
     3.1父类被重写方法的返回值类型是A类型,则子类重写的方法返回值类型可以是A类或者A的子类(引用数据类型)
     3.2父类被重写方法的返回值类型是基本数据类型,子类重写的方法返回值类型也必须是基本数据类型
    基本数据类型形如:byte、short、int、long、float、double、char、boolean等
    引用数据类型:是一个对象类型,它的值是指向内存空间的引用,就是地址
    3.3父类被重写方法的返回值类型是void类型,则子类重写的方法返回值也必须是void类型
4.子类和父类的同名同参数的方法要么都声明为非static的,要么都声明为static(都声明为static是重写了)

使用样例:
Student类重写了Person类中的方法
Person类:

public class Person {
    //属性
    String name;
    int age;
    //构造器
    public Person(){
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    //方法
    public void eat(){
        System.out.println("吃饭");
    }
    public void walk(int distance){
        System.out.println("走了"+distance+"公里");
    }
}

学生类:

public class Student extends Person{
    String major;
    public Student(){
    }
    public Student(String major){
        this.major = major;
    }
    public void Study(){
        System.out.println("学习的专业是:"+major);
    }
    public void eat(){
        System.out.println("学生应该吃点有营养的食物");
    }
    @Override
    public void walk(int distance) {
        System.out.println("方法的重写");
    }
}

1.5.1 方法重载与方法重写的区别:

二者的定义角度看
       方法重载: 两同一不同“同一个类,同样的方法名,只是形参列表不同,根据不同的形参列表判断是哪一个方法”
       方法重写: 在继承的基础之上,子类重写父类的方法,在创建子类对象调用时会调用子类重写父类的方法
从编译和运行的角度看
       重载, 是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了*。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
       对于多态,*******只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”

1.6可变个数的形参

概述

可变个数的使用格式:数据类型…变量名
传入的参数格式可以是1,2,3…

使用样例

public void show(String...strs){
        System.out.println(strs);
    }

     2.可变个数的形参方法可以与本类方法名相同,参数不同的形参方法实现共存
show(String s)
show(String…s)
    3.可变个数的形参方法需要声明在末尾
使用样例:
public void show(int i,String…strs){
       System.out.println(strs);
    }

1.7递归地使用

概述:

     1.递归方法: 一个方法体内调用自身;

     2.递归方法包含了一种隐含式的循环控制,它会重复执行其中的一段代码,但是它不需要使用循环控制;
     3.递归一定要向一直方向递归

使用样例:

//给出递归式f(0) = 1; f(1) = 4;
    //f(n+2) = 2*f(n+1)+f(n);
    public int f(int n) {
        if (n == 0) {
            return 1;
        } else if (n == 1) {
            return 4;
        } else {
            return 2 * f(n - 1) + f(n - 2);
        }
    }

2.进阶基础知识

2.1面向对象的特征

2.1.1面向对象的特征之一封装和隐藏

理解性内容 :

1.高内聚:类的内部操作细节自己完成,不允许外部干涉; 低耦合:进对外暴露少量的方法用于使用隐藏对象内部的复杂性,之对外公开简单的接口。便于外界的调用,从而提高系统的可扩展性、可维护性。
通俗的说,---------把该隐藏的隐藏起来,该暴露的暴露出来,这就是封装性的设计思想。

概述:

2.****封装:把属性封装起来,把该属性的权限设置为私有变量,对外部不可见(不可以直接调用,必须使用方法),但是可以使用方法来使用该属性【存在但是用不了】需要对属性加上额外的限制条件

官方一点的介绍: 当我们创建一个类的对象的时候,我们可以通过“对象.属性”的方式,对对象的属性进行赋值,
这里赋值操作会受到属性的数据类型和存储范围的制约。----------除此之外,没有其他的限制条件
【 但是在实际的问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加,同时需要避免用户使用“对象.属性”的方式进行赋值,此时就体现了 封装性;

3.封装性的体现:我们将类的对象属性私有化(private),并且提供公共的方法进行获取(getXXX)和设置(setXXX)[仅仅是这一点体现了封装性,并不代表这就是封装性] 另一个使用:不对外暴露的方法,类的内部的方法使用

4.封装性的体现,需要权限修饰符来配合

2.1.1.1知识拓展之四种权限修饰符

1 Java规定的四种权限(从小到大排列):private、缺省(default)、protected、public

修饰符 类内部 同一个包中 不同包的子类中 同一个工程
private Yes
default(缺省) Yes Yes
protected Yes Yes Yes
public Yes Yes Yes Yes

2四种权限可以修饰类的内部结构:属性、方法、构造器、内部类
     在修饰类的时候,只能使用缺省(默认情况下的)、public
      //如果类是缺省,在不同的包中,即使属性是public也不能使用;
3.对象对于不同权限属性和方法的调用规则
    3.1对于同一个包同一个类,所有的属性和方法都可以调用
    3.2对于同一个包的普通类,可以使用除private修饰的方法和属性其他的都可以调用
     3.3对于不同包的子类,可以重写和使用protected和public修饰的属性及方法
    3.4对于不同包的普通类(和其他的的类没有任何的关系),只能使用public修饰的属性和方法

4.总结:Java提供了四种权限修饰符类修饰类及类的内部结构,体现类及类的内部结构在被调用时可见性的大小;

2.1.2面向对象的特征之二继承

1.概念:
    官方概念: 继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

    个人理解: 继承就是说一个类2可以继承另一个类1,类1里面—所有—的属性,方法类2都可以直接使用,不用再另外声明。
注解:使用private修饰的成员变量实际上继承到了,但是由于封装性的影响,只能使用set和get来进行设置和获取
2.继承的好处:
    2.1:减少了代码的冗余度,提高了代码的复用性;子类可以直接使用父类的成员变量,方法
    2.2:便于功能的扩展;如果有多个子类都拥有某一个方法可以在父类中声明,所有用到的子类直接调用即可
    2.3:为之后多态性的使用提供了前提
3.继承的格式:
     class A extends B{}
      A:子类、派生类、subclass;
      B:父类、超类、基类、superclass;
    3.1继承的体现:一旦子类A继承父类B之后,子类A就获取了父类B中声明的所有属性和方法
    3.2子类继承父类以后,子类可以定义自己的属性和方法,实现功能的拓展;
    3.3子类和父类的关系:子类的功能更丰富一些

4.Java中关于继承的规定

    4.1一个类可以被多个子类继承;
    4.2Java中类的继承性:一个类只能有一个父类
    4.3子父类是相对的概念;
     4.4子类直接继承的父类,称为:直接父类。间接继承的父类成为:间接父类
    4.5子类继承父类以后,就获取了直接父类以及间接父类的所有属性和方法

使用样例:
Person类:

public class Person {
    //属性
    String name;
    int age;
    //构造器
    public Person(){
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    //方法
    public void eat(){
        System.out.println("吃饭");
    }
    public void walk(int distance){
        System.out.println("走了"+distance+"公里");
    }
}

student类:

public class Student extends Person{
    String major;
    public Student(){
    }
    public Student(String major){
        this.major = major;
    }
    public void Study(){
        System.out.println("学习的专业是:"+major);
    }
    public void eat(){
        System.out.println("学生应该吃点有营养的食物");
    }
    @Override
    public void walk(int distance) {
        System.out.println("方法的重写");
    }
}

2.1.3面向对象的特征之三多态

秒懂多态:

     1.理解多态性: 可以理解为一个事务的多种形态
    2.多态的使用规则: 在创建对象的时候使用如下规则
          —> 父类 对象名 = new 父类的人一个子类
          样例:Person m1 = new Man();
    3.何为多态性:父类的引用指向子类的对象(或者子类的对象赋给父类的引用)
    4.多态的使用,-----虚拟方法的调用-----
有了对象的多态性以后,我们在编译期间,只能调用父类中声明的方法,但是在运行期, 我们实际上执行的是子类重写父类的方法
    总结:编译看左边,执行看右边;父类的方法称为虚拟方法

5.多态的使用前提
    5.1有继承关系
    5.2子类重写父类的方法 (子类通常都会重写方法,要不然就没有必要[new 子类],使用多态)
        备注:***只能调用父类拥有的方法 ***,但是执行的时候使用的是右边重写的
6.对象的多态性:只适用于方法,不适用于属性(属性在子类和父类中都有,会调用父类的属性值)
7.多态只能调用父类的方法,不能调用子类的方法

使用样例:
  public class AnimalTest {

    public static void main(String[] args) {
        AnimalTest test = new AnimalTest();

        //多态的使用
        test.func(new Dog());

        test.func((new Cat()));
    }

    public void func(Animal animal){//实际的使用过过程中Animal animal = new 对象类();
        animal.eat();
        animal.shout();
    }


}

class Animal{

    public void eat(){
        System.out.println("动物:进食");
    }

    public void shout(){
        System.out.println("动物:叫");
    }
}

class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    @Override
    public void shout() {
        System.out.println("汪!汪!汪!");
    }
}

class Cat extends Animal{

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

    @Override
    public void shout() {
        System.out.println("喵!喵!喵!");
    }
}

2.2类的结构

2.2.1类的结构之一属性

概述:

属性也就是我们通常所说的成员变量,就好比一个汽车,他有自己的颜色、品牌、价格…这些都属于它的属性

使用样例:

class Person{

    //成员变量
    private String name;
    private int age;

}

------------------------------------------分割线-----------------------------------------

2.2.2类的结构之二方法

概述:

方法就是我们通常所理解的函数,只是他有自己的是使用格式
方法使用格式:
      权限修饰符 返回值类型 方法名(形参列表){方法体}

      它可以实现一个或者多个功能,例如:我们可以通过一个方法完成一个数组的排序,我们也可以完成一个数组的输出,数组的交换等等功能

使用样例:

public class ArrayUtil {

    //求数组的最大值
    public int getMax(int[] arr) {

        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }


    //求数组的最小值
    public int getMin(int[] arr) {

        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

    //求数组的平均值
    public int getAvg(int[] arr) {

        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum / arr.length;
    }


    //反转数组
    public void reverse(int[] arr) {

        for (int i = 0; i < arr.length / 2; i++) {
            int temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }

    }

    //数组排序
    public void sort(int[] arr) {

        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                /*if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }*/
                swap(arr,j,j+1);
            }
        }
    }

    //数组中两个数值的交换
    public void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //复制数组

    public int[] copy(int[] arr) {

        int[] arr1 = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = arr[i];
        }
        return arr1;
    }
    //遍历数组

    public void print(int[] arr) {

        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }

    //查找指定元素
    /*
     * 判断语句里面设置返回的时候,在方法结束的时候也需要设置返回值*/
    public int findIndex(int[] arr, int value) {

        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value) {
                return i;
            }
        }
        return -1;//如果没有找到返回-1;
    }


}

2.2.3类的结构之三构造器

概述:

构造器:首先,构造器是在类中声明的,分为有参构造器和无参构造器,有参构造器又可以按照自己的意愿想把几个成员变量放入构造器的形参列表就把几个成员变量放入形参列表,通俗地理解构造器就是在创建类的对象的时候可以初始化对象的成员变量

构造器的作用:
(1)创造对象 new + 构造器[Person()]
(2)初始化对象的属性

如果没有显式地定义类的构造器,系统会给出一个默认的构造器
定义构造器的格式:权限修饰符 类名(形参列表){}

使用格式

//构造器
    public Person() {
        System.out.println("Person构造器的使用");
    }

//带参的构造器
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

使用样例:

public class PersonTest {
    public static void main(String[] args) {

        //创建对象 new +  构造器[Person()]
        Person p1 = new Person();
        p1.eat();
        p1.study();
    }
}

class Person {

    //属性
    String name;
    int age;

    //构造器
    public Person() {
        System.out.println("Person构造器的使用");
    }

    //带参的构造器
    
    //初始化一个变量
    public Person(String name){
        this.name = name;
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //方法
    public void eat() {
        System.out.println("吃饭");
    }
    public void study() {
        System.out.println("学会面向对象");
    }
}

拓展:JavaBean[了解]

JavaBean是指使用Java语言写成的可重用组件 主要有以下特点:
    类是公共的 带有一个公共的无参构造器 有属性并且有对应的get和set方法

2.2.4类的结构之四代码块

1.代码块的作用:用来初始化类、对象;如果代码块有修饰的话只能是static的
2.分类
❤️2.1静态代码块
          内部可以有输出语句;
          随着类的加载而加载,而且只执行一次
          如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
          静态代码块只能执行静态的属性、静态的方法,不能调用非静态结构
          作用:初始化类的信息
❤️2.2非静态代码块
          内部可以有输出语句
          随着类的加载而执行
          每创建一个对象,就执行一次非静态代码块
          如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
          非静态代码块只能执行静态的属性、静态的方法,也可以能调用非静态结构{所有都可以调用}
          作用:在对象创建时,对对象的属性等进行初始化

总结:
对属性赋值的位置:
1.默认初始化
2.显式初始化
3.构造器初始化
4.通过"对象.属性"或者"对象.方法"的方法,进行赋值
5.在代码块中复制

代码块使用样例:

public class BlockTest {

    public static void main(String[] args) {


        System.out.println(Person.desc);

    }
}

class Person{
    String name;
    int age;
    static String desc = "人";

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //静态代码块[随着类的加载而加载]
    static{
        desc = "爱学习的人";
        System.out.println("hello,static block");
    }

    //非静态代码块[随着对象的创建而加载]
    {
        System.out.println("hello,static block");
    }

    public void eat(){
        System.out.println("吃饭");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public static void info(){
        System.out.println("中国人");
    }
}

2.2.5类的结构之五内部类(了解)

概述:
         当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

1.Java中允许将一个类A声明在另一个类B中,则A类就是内部类,类B就是外部类

2.内部类的分类:成员内部类 vs 局部内部类
       2.1成员内部类
          (1)内部类一方面作为外部类的成员
          可以调用外部类的方法
          可以被static修饰、四种权限修饰符修饰
          (2) 另一方面作为类出现
          可以有属性方法构造器
          可以被final修饰表示此类不可以被继承
          可以被abstract修饰
3.重点关注如下几个问题
        3.1如何实例化成员内部类的对象
        3.2如何在成员内部类中区分调用外部类的结构
        3.3开发中局部内部类的使用

public class InnerClassTest {

    public static void main(String[] args) {

       //3.1 创建静态内部类的对象
       //对于静态随着类的加载而加载,可以直接使用Person.Student()的方法new对象
        Person.Student student = new Person.Student();
        student.method();
        //创建非静态内部类的对象
        //对于非静态只有有了外部类的对象才有了非静态内部类的结构
        Person p = new Person();
        Person.Teacher teacher = p.new Teacher();
        teacher.method();

        teacher.show("黄鹂");
    }
}

class Person{

    String name = "李华";
    int age;

    //成员内部类
    //静态内部类
    static class Student {
        public void method(){
            System.out.println("学生内部类的使用");
        }
    }

    //非静态成员内部类
    class Teacher {

        String name = "教师";

        public void show(String name){
        	//3.2展示样例
            System.out.println(name);
            System.out.println(this.name);
            System.out.println(Person.this.name);
        }
        public void method(){
            System.out.println("教师内部类的使用");
        }
    }
}

2.3关键字的使用

2.3.1this关键字

概述:

this关键字的使用:
1.this可以用来修饰:属性、方法、构造器

2this对属性,方法的使用
❤️ 2.1 [因为方法的形参和类的属性重名,因此需要区分属性和形式参数]this.理解为当前的属性
this.age = age

❤️ 2.2在类的构造器中我们可以使用“this.属性”或者“this.方法”的方式,调用当前正在创建对象的属性或者方法
但是,通常情况下,我们可以省略“this.”,只有在方法的形参和类的属性重名时使用“this.属性”来进行区分形参和类的属性

3.使用this调构造器的方法
      this调用构造器的作用:可以降低代码的冗余度,即在别的构造器中书写的可以直接在当前的构造器中调用
❤️ 3.1我们在类的构造器中,可以显式的使用“this(形参列表)”方式,调用本类中指定的其他构造器。
❤️ 3.2构造器中不能通过“this(形参列表)”方式调用自己
❤️ 3.3若果一个类中有n个构造器,则最多有n - 1个构造器使用了“this(形参列表)”方式
❤️ 3.4规定:“this(形参列表)”必须声明在当前构造器的首行
❤️ 3.5构造器的内部,最多只能声明一个“this(形参列表)”,用来调用其他的构造器

使用样例:

  //有参和无参的构造器
    public Person(){
        System.out.println("省略40行代码");
        System.out.println("调用了构造器1");
    }


    public Person(String name){
        this.name = name;
        System.out.println("调用了构造器2");
    }

    public Person(int age){
        this();//调用了无参数的构造器
        this.age = age;
        System.out.println("调用了构造器3");
    }


    public Person(String name,int age){
        this(age);//调用有参数的构造器
        this.name = name;
        //this.age = age;//使用有参数的构造器所以这一行可以省略
        System.out.println("调用了构造器4");
    }

2.3.2package关键字

说明
❤️ 1.1为了更好的实现项目中类的管理,提供包的来源
❤️ 1.2使用package声明类或者接口所属的包,声明在原文件的首行
❤️ 1.3包属于标识符,遵循标识符的命名规则,做到见名知义,实际上在写类的成员变量,方法时我们都是遵循这样的规则,经过变量名或者方法名就可以大概的知道变量或者方法的功能是什么

❤️ 1.4每一个”.“代表一层目录

2.3.3import关键字

说明:
❤️ 2.1在源文件中显式的使用import结构导入指定目录下的类、接口
❤️ 2.2声明在包的声明和类的声明之间
❤️ 2.3如果是java.long包或者是本包下定义的可以省略
❤️ 2.4如果使用不同包下相同的类就需要有一个类使用全类名的方式定义

package和import关键字的使用样例代码:

package day03.com.it.java3;

import day02.com.it.exer1.Circle;
import day03.com.it.exer.Person;
import day03.com.it.exer3.Customer;

import java.util.Scanner;

/**
 * @BelongsProject: com.java.li
 * @BelongsPackage: day03.com.it.java3
 * @Auther:Administrator
 * @Creattime:2022/4/1114:17
 * @Description:关键字的测试
 */
public class PackageImportTest {
    public static void main(String[] args) {

        Circle circle = new Circle();
        
        Scanner scanner = new Scanner(System.in);

        Person person = new Person();

        Customer customer = new Customer("hua","li");
    }
}

2.3.4super关键字

理解性概念:

1.super理解为:super是在继承的基础上使用的 表示:父类的…
2.super可以用来调用:属性、方法、构造器

3.super的使用

❤️3.1 我们在子类的方法或构造器中,通过使用"super.属性"或"super.方法"的方式显式的调用父类中声明的属性或者方法。
但是,在通常情况下,我们可以省略"super."
❤️3.2特殊情况下。当父类和子类出现同名的属性时,我们想要在子类中调用父类的属性,则必须显式的使用"super.属性"的方法,表明调用的是父类中声明的属性
❤️3.3特殊情况:当子类重写了父类的方法后,我们想要在子类中调用父类的方法,则必须显式的使用"super.方法"的方式,表明调用的是父类中声明的方法

4.super调用关键字
❤️4.1我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定构造器
❤️4.2"super(形参列表)"的使用,必须声明在子类构造器的首行
❤️4.3我们在类的构造器中对于this(形参列表)或super(形参列表)只能二选一,不可同时使用
❤️4.4在构造器的首行,没有显式的声明使用this(形参列表)或super(形参列表),则会默认调用super();[空参构造器]
❤️4.5在类的构造器中,至少有一个类的构造器使用了super(形参列表),调用了父类的构造器

使用样例:
Person为父类

public class Person  {

    //属性的定义
    String name;
    int age;
    int id = 1001;//表示身份证号

    //构造器
    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //方法
    public void eat() {
        System.out.println("喜欢吃螺狮粉");
    }

    public void walk() {
        System.out.println("喜欢散步");
    }

    public void show(){
        System.out.println("name=" + this.name + "," + "age=" + this.age);
    }
}

Student为子类:

public class Student extends Person{

    String major;
    int id = 1002;//表示学号
    public Student(){
        super();//默认情况下都会调用父类的空参构造器
    }

    public Student(String name,int age,String major){
        super(name,age);//调用父类的构造器
        this.major = major;
    }

    @Override
    public void eat() {
        System.out.println("学生:多吃有营养的食物");
    }

    public void study(){
        System.out.println("学生:学习Java");
    }

    //super使用样例:
    public void show(){

        super.show();//调用父类的show()方法
        System.out.println("学习的专业是:"+this.major);
        System.out.println(this.id);
        System.out.println(super.id);//显式的调用父类的id
    }
}

2.3.5instanceof关键字

说明:

instanceof关键字是在进行向下转型(父类类型转化为子类类型的时候使用的关键字),使用格式为 a instanceof A

理解性内容:

1.a instanceof A:判断对象a是否是类A的实例,如果是,返回true,如果不是返回false
2.使用情景:为了避免向下转型出现ClassCastException的异常,我们再向下转型之前,先进性instanceof判断,如果返沪出现true,就向下转型,如果返回false不向下转型
3.转型说明
      自动转型:(向上转型)多态的使用,实际上创建了一个父类类型的对象
使用格式:父类类型 变量名 = new 子类类型();
向下转型:将父类类型对象强制转型为子类类型
使用格式:子类类型 变量名 = (子类类型) 变量名;

使用样例:

  Person p2 = new Man();
          if (p2 instanceof Man){
              Man m3 = (Man) p2;
              m3.earnMoney();
              System.out.println("********man*******");
          }
          if (p2 instanceof Woman){
              Woman w2 = (Woman) p2;
              System.out.println("********woman*******");
          }

2.3.6static关键字

1.static:静态的
2.static可以用来修饰属性、方法、代码块、内部类
3.static修饰属性:静态变量
❤️3.1:按是否使用static又分为:静态属性 和 非静态属性(实例变量)
      实例变量:我们创建了类的多个对象,每个对象都拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时, 不会导致其对象的其他属性值修改。
      静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的(有一个地方改,所有对象都会自动修改,使用用同一个静态变量)
❤️ 3.2:static修饰属性的说明:
3.2.1:静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
3.2.2静态变量的加载要早于对象的加载
3.2.3由于类只会加载一次,则静态变量在类中只会存储一份,存储在静态方法区

名称 类变量 实例变量
yes no
对象 yes yes

4.static修饰方法:静态方法
❤️ 4.1随着类的加载而加载,可以通过"类.方法"的方式进行调用
❤️ 4.2

名称 类方法 实例方法
yes no
对象 yes yes

❤️ 4.3静态方法:只能调用静态的方法或者属性
          非静态方法:接可以调用静态的方法或者属性,也可以调用非静态的方法或者属性
5.备注:
❤️ 5.1 在静态方法中,不能使用this关键字、supper关键字
❤️ 5.2 关于静态属性和静态方法的使用,都可以从生命周期的角度考虑
        总结:静态属性和静态方法由于在类加载的时候就加载,所以可以通过"类."形式进行使用,后创建的对象可以调用已经加载的静态属性或者方法
6.开发中,如何确定一个属性是否要声明为static的?
        属性可以被多个对象所共享的,不会随着对象的不同而不同
7.开发中,如何确定一个方法是否要声明为static的?
         操作静态属性的方法,通常设置为静态的
        工具类中的方法,习惯上声明为static的。比如:Math、Array、Collections

2.3.7***abstract关键字

概述:
    随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
abstract表示抽象的,可以用来修饰类、方法。
举例:
    有一个几何图形类,里面有求出几何图形面积的方法,但是不知道几何图形的种类所以只能将此方法设置为抽象的,让具体的类(可以是圆,长方形,三角形,正方形等等)来继承实现此方法,写出具体的求面积公式

说明:

1.abstract:抽象的
2.abstract可以用来修饰类、方法
     2.1abstract修饰类:抽象类
      此类不能实例化
      抽象类中一定有构造器,便于子类实例化调用(设计子类实例化的全过程)
      开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
     2.2abstract修饰方法:抽象方法
      抽象方法只有方法的声明,没有方法体

      包含抽象方法的类,一定是抽象类,反之抽象类中是可以没有抽象方法的
      若子类重写了父类所有的抽象方法后,子类可以实例化(换言之不用变成抽象类)
      若子类没有重写了父类所有的抽象方法后,子类不能够实例化
3.abstract不能修饰私有方法、静态方法、final的方法、final的类
      3.1 私有方法是不能被重写的,但是abstract修饰的方法,必须被重写(除抽象子类外)
      3.2 静态方法:子类和父类同名同参的方法都要是非static的,都声明为static的不是重写
      3.3 finial表示最后的方法,不能被重写,只能被调用,abstract要求被继承且重写
      3.4 final修饰的类,表明不能被继承

总结:

    1.含有抽象方法的类是抽象类,抽象类不能实例化创建对象,抽象类有构造器便于子类使用
    2.子类继承父类之后,若父类是抽象的,就需要重写父类以及父类的父类所有的抽象方法,否则该子类也要变成抽象的

使用样例:

测试类:

public class AbstractTest {

    public static void main(String[] args) {

        //Person类没有变成抽象类以前,可以new对象;---不可实例化
        /*Person p1 = new Person();
        System.out.println(p1);*/
        Student student = new Student("李华",28,"男");



    }
}

抽象类 CreatPerson

abstract class CreatPerson{

    public abstract void breath();
}

抽象类Person:

abstract class Person extends CreatPerson{
    String name;
    int age;

    public Person(){
    }

    public Person(String name ,int age){
        this.name = name;
        this.age = age;
    }

    //变成抽象的,所以子类需要进行重写
    public abstract void eat();

    public void walk(){
        System.out.println("人走路");
    }
    
}

抽象类Student

class Student extends Person{


    String sex;

    public Student(){
    }

    public Student(String name,int age,String sex){
        super(name, age);
        this.sex = sex;
    }

    @Override
    public void eat() {
        System.out.println("学生吃饭");
    }

    @Override
    public void breath() {
        System.out.println("学生呼吸");
    }
}

2.3.8***Interface关键字

概述:
    一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
    另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都支持USB连接。

接口描述:
1.接口使用interface来定义
2.Java中,接口和类是并列的两个结构
3.如何定义接口:定义接口的成员
          3.1 JDK7以前:只能定义全局常量和抽象方法
        >全局常量:public static final的,但是书写时可以省略
        >抽象方法:public abstract的

        3.2JDK8:除定义全局常量和抽象方法之外,还可以定义静态方法,默认方法

接口的特性:
4.接口中不能定义构造器,接口不可以实例化
5.Java开发中,接口通过类来实现(implemennts)的方法来使用,如果实现类覆盖了接口中的所有抽象方法,类就可以造对象,否则此实现类仍为一个抽象类
6.Java类可以实现多个接口,弥补了Java单继承的局限性
7.接口与接口之间可以实现继承,而且可以实现多继承
8.接口的具体实现:体现了多态性
9.接口,可以看作是一种规范

使用样例:
接口测试类:

public class InterfaceTest {

    public static void main(String[] args) {
        
        System.out.println(Flyable.MAX_SPEED);
        System.out.println(Flyable.MIN_SPEED);
        Plane p = new Plane();
        p.fly();
        p.stop();
    }
}

飞行接口:

interface Flyable{

    //全局变量
    public static final int MAX_SPEED = 7900;
    int MIN_SPEED = 1;

    //抽象方法
    public abstract void fly();
    void stop();//省略了 public abstract

}

攻击接口:

interface Attackable{

    void attack();
}

飞机类:

class Plane implements Flyable{

    @Override
    public void fly() {
        System.out.println("飞机通过引擎飞行");
    }

    @Override
    public void stop() {
        System.out.println("驾驶员减速停止");
    }
}

风筝类:
由于设置为抽象类,所以可以不用重写接口中的方法

abstract class Kite implements Flyable{
}

Java类可以实现多个接口,弥补了Java单继承的局限性
子弹类:

class Bullet implements Flyable,Attackable,CC{


    @Override
    public void fly() {
    }

    @Override
    public void stop() {
    }

    @Override
    public void attack() {
    }

    @Override
    public void method1() {
    }

    @Override
    public void method2() {
    }
}

7.接口与接口之间可以实现继承,而且可以实现多继承

interface AA{
    void method1();
}

interface BB{
    void method2();
}

interface CC extends AA,BB{
}

2.4零散知识点总结

2.4.1equals()方法的使用

2.4.1.1"=="和equals之间的区别

1.“==”的使用:
1.1本身是一个运算符
1.2可以使用在基本数据类型和引用数据类型中
1.3如果是基本数据类型,永远比较两个变量保存的数据(不一定是相同类型)
1.4如果是引用数据类型,永远比较的是两个变量的地址

使用样例:

int i = 10;
        int j = 10;
        System.out.println(i == j);//true

        char k = 10;
        System.out.println(i == k);//true

        double n = 10.0;
        System.out.println(i == n);//true

        //引用数据类型的测试
        Customer c1 = new Customer("李华",21);
        Customer c2 = new Customer("李华",21);
        System.out.println(c1 == c2);//false

2.equals的使用:
2.1本身是一个方法
2.2只适用于引用数据类型的测试
public boolean equals(Object obj){
return (this == obj);
}
2.3 equals的功能和== 是一样的,比较的是地址值
备注:相同的字符串的地址是一样的
2.4像String、Date、File都重写了Object里面的equals方法重写以后比较的就是数值了
2.5自定义类如何重写equals方法,实现比较实体内容是否相同

    //重写equals方法
@Override
public boolean equals(Object obj) {
    if (this == obj){
        return true;
    }
    if (obj instanceof Order){
        Order o1 = (Order) obj;
        if (this.orderId == o1.orderId && this.orderName.equals(o1.orderName)){
            return true;
        }
    }
    return false;
}
测试
public static void main(String[] args) {
        Order o1 = new Order(12,"李华");
        Order o2 = new Order(12,"李华");

        System.out.println(o1.equals(o2));//true
    }

2.4.2toString()方法的使用

[了解内容]
概述:

toString()我们再调用的时候对于String、Date、File、包装类都默认重写了方法,所以会输出对象的具体信息,但是在我们创建一个类的对象【好比Person类】的时候会输出对象所在的地址,所以在编写Person类的时候,一会都会重写toString()方法

Object类中toString()方法的测试:

1.当我们输入一个对象的引用时,实际上输出的就是对象的toString()方法即下面两句是等价
System.out.println(c1);
System.out.println(c1.toString());

2.Object类中toString()方法的定义:

public String toString() {
      return getClass().getName() + "@" + Integer.toHexString(hashCode());
      }

3.像String、Date、File、包装类都重写了toString()方法,输出的都是实体对象的具体信息;
String str = new String(“MM”);
System.out.println(str);//MM
4.自定义类也可以实现toString方法的重写
重写样例:
@Override
public String toString() {
return “Customer[name=:”+name+“,age=:”+age+“]”;
}

2.4.3 单例模式

1.单例设计模式:
     所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
2.区分饿汉式和懒汉式
    饿汉式:
    坏处:对象加载时间较长
    好处:线程安全

  public class SingletonTest1 {
        public static void main(String[] args) {
            Bank bank1 = Bank.getInstance();
            Bank bank2 = Bank.getInstance();
            System.out.println(bank2 == bank1);//查看是否是一个对象
        }
    }

  //饿汉式
    class Bank{
        //1.私有化类的构造器
        private Bank(){
        }
        //2.创建类的对象
        private static Bank instance = new Bank();
        //3.提供公共静态的方法返回对象(只能通过类.对象的方法调用,所以设置为static)
        public static Bank getInstance(){
            return instance;
        }
    }

   懒汉式:
        好处:延迟对象的创建
        坏处:目前是不安全的
    public class SingletonTest2 {
        public static void main(String[] args) {
            Order o1 = Order.getInstance();
            Order o2 = Order.getInstance();
            System.out.println(o2 == o1);
        }
    }

    
  懒汉式  不着急创建对象就不急着创建--懒汉式
class Order{
    //创建私有化构造器
    private Order(){
    }
    //创建对象名
    private static Order instance = null;
    //提供公共的方法返回对象
    public static Order getInstance(){
        //如果当前没有创建对象,就重新创建对象
        if (instance == null){
            instance = new Order();
            return instance;
        }
        return instance;
    }
}

3.单例模式的优点
     由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决

你可能感兴趣的:(#,JavaSE,java)