Java面向对象知识点

Posted yfyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面向对象知识点相关的知识,希望对你有一定的参考价值。

JavaSE 面向对象

面向对象:用代码模拟现实世界,为人类的业务服务

面向对象重要的概念
  • 类:描述相同事务的共同特征的抽象
  • 对象:具体存在的实例,是真实的
代码层面:必须先有类,才有对象

类名的注意

  • 类名首字母应该大写,满足”驼峰命名“
  • 一个Java代码文件中可以定义多个类,但是只能有一个类是public修饰,且用public修饰的类名必须成为代码的文件名称

类中的成分 -- 五大成分

  • 成员变量(Field):描述类和对象的属性信息
  • 成员方法(Method):描述类或者对象的行为信息
  • 构造器(Constructor):初始化一个类的对象并返回引用
  • 代码块
  • 内部类
public class ClassDemo1 {
    System.out.println("Hello,World");
}

//报错原因,其不是类中的成分!,必须是五大成分。

构造器

  • 作用:初始化类的对象并返回引用

  • 格式:

    修饰符 类名 (形参) {}

  • 构造器初始化对象:

    类名 对象名称 = new 构造器;

注意:一个类默认自带一个无参构造器,若手动写一个,自带无参构造器就会被覆盖

this关键字

  • 作用:this代表了当前对象的引用,this关键字可以用在实例方法和构造器中
    • this用在方法中,谁调用这个方法,this就代表谁
    • this用在构造器中,代表了构造器正在初始化的那个对象的引用

封装

  • 作用:实现代码的组件化,以及提高所谓的安全性
  • 规范:建议成员变量私有、提供成套的get/set xxx 取值和赋值
    • private修饰的方法,成员变量,构造器等只能在本类中被直接访问
    • public修饰符,是公开的意义
  • 小结:封装的核心思想是 合理隐藏,合理暴露

static关键字

  • 作用:Java通过成员变量是否有static修饰,来区分是属于类的还是属于对象的

使用static修饰的成员(方法和成员变量)属于类本身的,否则便是属于对象的

按照有无static修饰,成员变量和方法可以分为:

  • 成员变量

    • 静态成员变量(有static):也叫类变量,属于类本身,直接使用类名访问即可

      静态成员变量有static修饰,属于类本身,与类加载一次,因为只有一份所以可以被类和类的对象共享访问

    • 实例成员变量(无static):属于类的每个对象,必须使用对象访问

      属于对象,必须先创建对象,然后用对象去访问

  • 成员方法

    • 静态方法(有static):也叫类方法,属于类本身,直接用类名访问即可
    • 实例方法(五static):属于类的每个对象,必须用类的对象访问
package cn.imut._02成员变量;

public class Student {
    public static String schoolName = "IMUT";

    private String name;

    public static void main(String[] args) {
        //Student可以不写
        System.out.println(Student.schoolName);


        Student student = new Student();
        student.name = "实例变量";
        System.out.println(student.name);
    }
}

注意:不建议使用对象访问静态成员变量(静态成员方法),虽然可以访问。应该使用类访问

总结

  • 实例方法是否可以直接访问实例成员变量?可以,因为都属于对象
  • 实例方法是否可以直接访问静态成员变量?可以,因为静态成员变量可以被共享访问
  • 实例方法是否可以直接访问实例方法?可以,因为实例方法都是属于对象
  • 实例方法是否可以直接访问静态方法?可以,因为静态方法可以被共享访问
  • =============================================================
  • 静态方法是否可以直接访问问实例变量?不可以,实例变量必须用对象访问
  • 静态方法是否可以直接访问静态变量?可以,静态成员变量可以被共享访问
  • 静态方法是否可以直接访问实例方法?不可以,实例方法必须对象访问
  • 静态方法是否可以直接访问静态方法?可以,静态方法可以被共享访问

继承

继承是Java中一个特殊的关系,是一种子类到父类的关系。

被继承的类称为:父类/超类、继承父类的类称为:子类

  • 作用:提高代码的复用
  • 子类更强大
  • 特点:子类继承了一个父类,子类就可以得到父类的属性(成员变量)和行为(方法)了
  • But!,并不是所有父类的属性,行为子类都可以继承
    • 父类的构造器,子类无法继承

继承后成员变量的访问特点

  • 就近原则:子类有找子类、子类没有找父类、父类没有就报错
  • 总结
    • this代表当前对象的引用,可以用于访问当前子类对象的成员变量
    • super代表父类对象的引用,可以用于访问父类中的成员变量

继承后成员方法的访问特点

  • 同为就近原则
继承后构造器的特点
  • 子类所有构造器的第一行都会先

Java中继承的特点

  • 单继承:一个类只能继承一个直接父类
  • 多层继承:一个类可以间接继承多个父类
  • 一个类可以有多个子类
  • 一个类要么默认继承了Object类,要么间接继承了Object类

方法重写

子类继承了父类,子类变得到了父类的某个方法,但是子类若觉得父类的方法不好用,可以进行重写,从而覆盖父类的方法

方法重写的校验注解:@Override
  • Java建议在重写的方法上加一个@Override注解
  • 一旦加了注解,那就必须是成功重写父类的方法,否则报错
  • @Override优势:可读性好、安全、优雅!
方法重写的要求
  • 子类重写方法的名称和形参列表必须与父类被重写方法一样
  • 子类重写方法的返回值类型申明要么与父类一样,要么比父类的方法返回值类型范围更小
  • 子类重写方法的修饰符权限应该与父类被重写方法的修饰符权限相同或者更大
  • 子类重写方法申明抛出的异常应该与父类被重写方法申明抛出的异样一样或者范围更小
supper调用父类被重写的方法
  • supper:代表了父类的引用
  • supper可以用在子类的实例方法中调用父类被重写的方法

注意!静态方法和私有方法不可以被重写

总结

  • this代表了当前对象的引用(继承中指代子类对象)
    • this.子类成员变量
    • this.子类成员方法
    • this(...):可以根据参数匹配访问本类其他构造器
  • super代表了父类对象的引用(继承中指代了父类对象空间)
    • super.父类成员变量
    • super.父类的成员方法
    • super(...):可以根据参数匹配访问父类的构造器

引用类型

引用类型作为一种类型,可以在一切使用类型的地方使用!

抽象类

父类知道子类一定会完成某个功能,但是每个子类完成的情况是不同的。

子类会使用自己重写的功能,那么父类的该功能就可以定义成抽象方法,子类重写调用子类自己即可

类似于一个牌子,告诉子类一定会做重写这个功能!

子类一旦做了,重写父类的方法,父类的方法便没有任何用处,因此定义为抽象方法,且有抽象方法的类一定是一个抽象类

public class AbstractDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.run();
    }
}
class Dog extends Animal {
    @Override
    public void run() {
        System.out.println("狗跑的快");
    }
}
class Cat extends Animal {
    @Override
    public void run() {
        System.out.println("猫跑的快");
    }
}
abstract class Animal {
    //抽象方法没有方法体
    public abstract void run();
}
抽象方法:没有方法体,用abstract修饰
总结:抽象类就是约束子类要重写抽象方法

注意:一个类继承了抽象类,就必须重写完全部的抽象方法,否则这个类必须定义成抽象类

抽象类有得有失
  • 有得:拥有抽象方法的能力
  • 有失:不能创建对象

注意:抽象类除了不能创建对象,类的其他成分都具备!比如构造器,也是拥有的

注意:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

接口

接口是比抽象类更加抽象的抽象,接口中全都是抽象方法(JDK8之前),接口同样不能创建对象

接口体现的是规范思想,实现接口的子类必须重写完接口的全部抽象方法

核心关键字 interface

接口的继承

接口与类是多实现关系,一个类同时可以实现多个接口

接口与接口是多继承关系,一个接口可以同时继承多个接口

JDK1.8 之后,接口新增了三个方法

  • 默认方法
    • 必须使用default修饰
    • 默认加public修饰
    • 只能用接口的实现类的对象来调用
  • 静态方法
    • 可以直接加static修饰
    • 默认加public修饰
    • 接口的静态方法只能用接口的类名称本身调用
  • 私有方法(jdk1.9 开始支持)
    • 其实就是私有的实例方法,必须加private修饰
注意事项
  • 若实现了多个接口,多个接口中存在同名的静态方法并不会冲突,因为只能通过各自接口名访问静态方法
  • 当一个类,既继承一个父类,又实现若干个接口时,父类的成员方法与接口中的默认方法重名,子类就近选择执行父类成员方法
  • 当一个类实现多个接口时,多个接口存在同名的默认方法,实现类必须重写这个方法
  • 接口中,没有构造器,不能创造对象

代码块

  • 静态代码块:属于类,会与类一起加载,而且自动触发一次!

    public class CodeDemo {
        //在main上先加载
        static {
            System.out.println("静态代码块~");
        }
    
        public static void main(String[] args) {
    		System.out.println("main方法~");
        }
    }
    
  • 实例代码块:属于类的每个对象,随着对象一起加载。每次创建对象都触发执行一次

final关键字

final是”最终“的意思,可以修饰类、方法、变量

  • final修饰类,说明类不能被继承了
  • final修饰方法,方法不能被重写
  • final修饰变量,变量有且仅只能被赋值一次

注意:abstract 和 final 是互斥的关系!

枚举类

类的对象只有有限个、确定的。我们称此类为枚举类

  • 线程状态:创建、就绪、运行、堵塞、死亡

当需要定义一组常量时,强烈建议使用枚举类

如果枚举类中只有一个对象,则可以作为单例模式的实现方式

枚举类的实现
  • JDK1.5 之前需要自定义枚举类

    package cn.imut.test;
    
    //自定义枚举类
    public class Season {
        //1.声明Season的属性
        private final String seasonName;      //名称
        private final String seasonDesc;      //描述
    
        //2.私有化类的构造器,并给对象属性赋值
        private Season(String seasonName, String seasonDesc) {
            this.seasonName = seasonName;
            this.seasonDesc = seasonDesc;
        }
    
        //3.提供当前枚举类的多个对象
        public static final Season SPRING = new Season("春天","春暖花开");
        public static final Season SUMMER = new Season("夏天","夏日炎炎");
        public static final Season AUTUMN = new Season("秋天","秋高气爽");
        public static final Season WINTER = new Season("冬天","冰天雪地");
    
        //4.其他述求1:获取枚举类对象的属性
        public String getSeasonName() {
            return seasonName;
        }
    
        public String getSeasonDesc() {
            return seasonDesc;
        }
    
        //4.其他述求2:提供toString()
        @Override
        public String toString() {
            return "Season{" +
                    "seasonName=‘" + seasonName + ‘‘‘ +
                    ", seasonDesc=‘" + seasonDesc + ‘‘‘ +
                    ‘}‘;
        }
    }
    

    测试

    package cn.imut.test;
    
    public class SeasonTest {
        public static void main(String[] args) {
            Season summer = Season.SUMMER;
            System.out.println(summer);
        }
    }
    
  • JDK1.5 新增的 enum关键字用于定义枚举类

    package cn.imut.test;
    
    //使用enum关键字定义枚举类
    //说明:定义的枚举类默认继承于java.lang.Enum类
    public enum Season1 {
    
        //1.提供当前枚举类的对象,多个对象之间用逗号隔开,末尾对象分号结束
        SPRING("春天","春暖花开"),
        SUMMER("夏天","夏日炎炎"),
        AUTUMN("秋天","秋高气爽"),
        WINTER("冬天","冰天雪地");
    
        //2.声明Season的属性
        private final String seasonName;      //名称
        private final String seasonDesc;      //描述
    
        //3.私有化类的构造器,并给对象属性赋值
        private Season1(String seasonName, String seasonDesc) {
            this.seasonName = seasonName;
            this.seasonDesc = seasonDesc;
        }
    
        //4.其他述求1:获取枚举类对象的属性
        public String getSeasonName() {
            return seasonName;
        }
    
        public String getSeasonDesc() {
            return seasonDesc;
        }
    }
    
    

若枚举类只有一个对象,则可以作为一种单例模式的实现方式

Enum类的主要方法

常用

  • values()
  • valueOf(String str)
  • toString()
枚举类的属性
  • 枚举类对象的属性不应允许被改动,所以应该使用 private final 修饰
  • 枚举类使用 private final 修饰的属性应该在构造器中为其赋值
  • 若枚举类显式的定义了带参数的构造器,则在列出枚举值时也必须对应的传入参数
使用enum关键字定义的枚举类实现接口的情况
  • 情况一、实现接口,在enum类中实现抽象方法

  • 情况二

    public enum Season1 implements Info{
    
        //1.提供当前枚举类的对象,多个对象之间用逗号隔开,末尾对象分号结束
        SPRING("春天","春暖花开") {
            public void show() {
                System.out.println("春天在哪里");
            }
        },
        SUMMER("夏天","夏日炎炎") {
            public void show() {
                System.out.println("夏天在哪里");
            }
        },
        AUTUMN("秋天","秋高气爽") {
            public void show() {
                System.out.println("秋天在哪里");
            }
        },
        WINTER("冬天","冰天雪地") {
            public void show() {
                System.out.println("冬天在哪里");
            }
        };
    

总结

  • 枚举类是final修饰的,不能被继承
  • 枚举类默认继承了枚举类型:Java.lang.Enum
  • 枚举类的第一列罗列的是枚举类的对象,且用常量存储
  • 枚举类的构造器默认是私有的
  • 枚举类相当于多例对象

多态

同一个类型的对象,执行同一个行为,在不同的状态下会表现出不同的行为特征

识别技巧

  • 对于方法的调用:编译看左边,运行看右边
  • 对于变量的调用:编译看左边,运行看左边

多头的使用前提

  • 必须存在继承或者实现关系

  • 必须存在父类类型的变量引用子类类型的对象

  • 需要存在方法重写

优劣势

  • 优势
    • 右边对象可以实现组件化切换,业务功能也随之切换,便于扩展和维护
    • 实际开发中,父类类型作为方法形式参数,传递子类对象给方法,体现出扩展性和便利
  • 劣势
    • 多态形式下,不能直接调用子类特有的功能

引用类型强制类型转换

父类类型的变量或者对象必须强制类型转换成子类类型的变量,否则报错。

Java建议

使用 instanceof 判断前面的变量是否是后面的类型或者其子类类型才会返回 true

示例

  • 设计一个电脑,可以接入2个USB设备

Interface USB

public interface USB {
    void connect();     //插入
    void unConnect();   //拔出
}

class Mouse

//鼠标
public class Mouse implements USB {

    private String name;

    public Mouse(String name) {
        this.name = name;
    }

    public void dbClick() {
        System.out.println(name + "双击666");
    }

    @Override
    public void connect() {
        System.out.println(name + "成功插入");
    }

    @Override
    public void unConnect() {
        System.out.println(name + "成功拔出");
    }
}

class KeyBoard

public class KeyBoard implements USB {

    private String name;

    public KeyBoard(String name) {
        this.name = name;
    }

    public void keyDown() {
        System.out.println(name + "敲出键盘侠");
    }
    @Override
    public void connect() {
        System.out.println(name + "成功插入");
    }

    @Override
    public void unConnect() {
        System.out.println(name + "成功拔出");
    }
}

class Computer

public class Computer {
    public void installUSB(USB usb) {
        //usb有可能是一切
        usb.connect();
        if(usb instanceof Mouse) {
            ((Mouse) usb).dbClick();
        }else if(usb instanceof KeyBoard) {
            ((KeyBoard) usb).keyDown();
        }
        usb.unConnect();
    }
}

class Test

public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();

        USB lj = new Mouse("罗技");
        computer.installUSB(lj);

        USB hhkb = new KeyBoard("HHKB");
        computer.installUSB(hhkb);
    }
}

内部类

定义在一个类内部的类就是内部类

作用:可以提供更好的封装性,有更多的权限修饰符,有更多的控制

分类

  • 静态内部类:属于外部类本身,只会加载一次
  • 实例(成员)内部类:属于外部类,但是可以访问外部类的全部成员
  • 局部内部类:范围很小,几乎没用。
  • 匿名内部类

匿名内部类:一个没有名字的局部内部类,可以简化代码

特点

  • 匿名内部类是一个没有名字的内部类
  • 匿名内部类一旦写出来,就会立即创建一个匿名内部类的对象返回
  • 匿名内部类的对象的类型相当于是当前new的那个类型的子类类型

匿名内部类示例

package cn.imut._08匿名内部类;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Anonymity {
    public static void main(String[] args) {
        //创建窗口
        JFrame win = new JFrame("登录功能");
        //设置窗口大小
        win.setSize(400,300);
        //居中
        win.setLocationRelativeTo(null);
        //加按钮
        JButton btn = new JButton("登录");
        JPanel panel = new JPanel();
        panel.add(btn);
        win.add(panel);
        //监听器
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("用户点击触发了登录");
            }
        });
        //显示
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        win.setVisible(true);
    }
}

包和权限修饰符

包:管理各种不同的技术

相同的包下,类可以直接访问,不同的包下必须先导包。

权限修饰符:

(private --> 缺省 --> protected --> public)

四种修饰符的访问权限范围:

private 缺省 protected public
本类中
本包下其他类中 ×
其他包下的类中 × × ×
其他包下的子类中 × ×

以上是关于Java面向对象知识点的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段9——JS中的面向对象编程

java知识28 Java封装多测师

Java面向对象知识(上:基础篇)

Java中面向对象的三大特性之封装

Python面向对象学习之八,装饰器

重新梳理IT知识之java-05面向对象