详解final, abstract, interface关键字

news2024/10/7 12:29:33

一.final关键字

1.final关键字介绍

——final关键字可以去修饰类、方法、属性和局部变量

 

2.final关键字的作用

1)final修饰类,这个类不能被其他类继承

2)final修饰方法,方法不能被重写

3)final修饰属性,属性的值不能被修改

4)final修饰局部变量,局部变量的值不能被修改

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

//1.final修饰类,类不能被继承
final class Person {
}

//class Stu extends Person {}
//错误,Person类不能被继承


class Animal {
    //2.final修饰方法,方法不能被重写
    public final void say() {
    }
}

class Dog extends Animal {
    //错误,不能重写final的方法
    //public void say() {}
}


//3.final修饰属性,属性的值不能被修改
class Cat {
    private final int age = 10;

    public void setAge() {
        //错误,final修饰的属性不能被修改
        //age = 19;
    }
}


//4.final修饰局部变量,局部变量的值不能被修改
class Tiger {
    public void sleep() {
        final int age = 18;
        //final修饰的局部变量不能被修改
        //age = 19;
    }
}

 

3.final的细节讨论及实现

1)final修饰的属性叫做常量,常量使用全大写字母表示,若是多单词,单词间使用_隔开

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.MAX_AGE);//130
    }
}

class Person {
    public final int MAX_AGE = 130;
}

2)final修饰的属性必须要初始化,可以在三个地方初始化:

        a.声明定义并初始化

        b.构造器中初始化

        c.代码块中初始化

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        //使用
        System.out.println(person.MAX_AGE);//130
        System.out.println(person.MIN_AGE);//0
        System.out.println(person.MAX_NUM);//100
    }
}

class Person {
    //声明定义并初始化
    public final int MAX_AGE = 130;

    //构造器中初始化
    public final int MIN_AGE;
    public Person() {
        MIN_AGE = 0;
    }

    //代码块中初始化
    public final int MAX_NUM;
    {
        MAX_NUM = 100;
    }
}

3)若final修饰的属性是静态的,可以在两个地方初始化:

        a.声明定义并初始化

        b.静态代码块中初始化

public class Test {
    public static void main(String[] args) {
        //使用
        System.out.println(Person.MAX_AGE);//130
        System.out.println(Person.MIN_AGE);//0
    }
}

class Person {
    //声明定义并初始化
    public final static int MAX_AGE = 130;

    //静态代码块中初始化
    public final static int MIN_AGE;
    static {
        MIN_AGE = 0;
    }
}

4)final类不能被继承,但是可以实例化

public class Test {
    public static void main(String[] args) {
        //final类不能被继承,但是可以实例化
        Person person = new Person();
    }
}

final class Person {
}

5)若类不是final类,但含有final方法,那么final方法可以被继承,但不能被重写

public class Test {
    public static void main(String[] args) {
        Colleague colleague = new Colleague();
        colleague.say();//final方法可以被继承
    }
}

class Person {
    public final void say() {
        System.out.println("I say: you must success!");
    }
}

class Colleague extends Person {
    //不能重写父类中final修饰的方法
    //public void say() {}
}

6)若一个类已经是final类了,那么其方法没有必要设置为final方法了:因为final类不可能被继承,有final方法也不可能被重写

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

final class Person {
    //类已经是final修饰的了,那么方法不需要再使用final修饰
    //public final void say() {
    //    System.out.println("I will say: you must success!");
    //}

    public void say() {
        System.out.println("I will say: you must success!");
    }
}

7)final不能修饰构造器,能不能说说为什么?

        ——final修饰的方法约束在子类中不能进行重写,而构造器本身就不能在子类中重写,所以无需final修饰

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

class Person {
    //final不能修饰构造器
    //final public Person() {}
}

8)final和static搭配使用效率更高,不会导致类的加载就可以使用

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

class Person {
    //final和static搭配使用效率更高,不会导致类的加载就可以使用
    public static final int MAX_AGE = 150;

    //静态代码块随着类的加载而加载
    static {
        System.out.println("静态代码块被加载~");
    }
}

9)包装类(Integer、Double等)和String类均是使用final修饰的

 

 

二.抽象类

1.什么是抽象类?什么是抽象方法?

——使用abstract关键字修饰的类/方法叫做抽象类/方法

 

2.抽象类/方法格式

抽象类:权限修饰符 abstract class 类名 {}

抽象方法:权限修饰符 abstract 返回类型 方法名(形参列表...);

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

//当父类的某些方法需要声明,但是又不确定要怎么使用的时候,可以将方法声明为抽象类,那么这个类也是抽象类
//注意,只要方法是抽象方法,那么类也必须是抽象类
abstract class A {
    public abstract void say();
}

//使用abstract关键字修饰一个类时,这个类就叫做抽象类
abstract class B {
    //使用abstract修饰一个方法的时候,这个方法就是抽象方法,抽象方法无方法体
    public abstract void hi();
}

 

3.抽象类的应用场景

——当我们不知道父类的方法怎么使用的时候,可以把父类方法设置为抽象方法,让子类去实现这个抽象方法,含有抽象方法的类叫做抽象类

 

4.抽象类的细节讨论及实现

1)抽象类不能被实例化

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

//3.抽象类不能被实例化
abstract class C {
}

2)抽象类不一定要包含abstract方法,换种说法,抽象类可以没有抽象方法

3)一个类中只要有abstract方法,那么这个类也要使用abstract修饰

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

//抽象类不一定要包含abstract方法,也就是说,抽象类可以没有抽象方法
//一旦一个类中含有了抽象方法,那么这个类必须声明为抽象类
abstract class D {
    //抽象方法
    public abstract void method();

    //非抽象方法
    public void depart() {
        System.out.println("启程~");
    }
}

4)abstract只能修饰类和方法,不能修修饰其他属性

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

abstract class E {
    //抽象方法
    public abstract void radiant();
    //6.abstract只能修饰类和方法,不能修饰其他属性
    //public abstract int aae;
}

5)抽象类本质还是类,抽象类可以有任意成员【向上转型解决】

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

//抽象类的本质还是类,可以有任意成员: 非抽象方法、构造器、静态属性
abstract class F {
    //抽象方法
    public abstract void live();

    //成员变量
    public static int age = 10;
    public int data = 11;

    //构造器
    public F() {
    }

    //非抽象方法
    public void board() {
        System.out.println("board的意思是董事会~");
    }
}

6)抽象方法不能有方法体

7)如果一个类继承了抽象类,则它必须实现抽象类中的所有抽象方法或它也声明为抽象类

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

//如果一个类继承了抽象类,那么它必须实现抽象类的所有抽象方法,或者它也声明为抽象类
//抽象类
abstract class Person {
    //抽象方法不能有方法体
    public abstract void hi();
    public abstract void go();
}

//1)实现全部的抽象方法
class Teacher extends Person {
    public void hi() {
        System.out.println("hi,bro~");
    }

    public void go() {
        System.out.println("bro,go,go,go~");
    }
}

//2) 将自己也声明为抽象类
abstract class Stu extends Person {
}

8)抽象方法不能使用private、final和static关键字修饰,因为这些关键字都与重写相违背

//1)为什么不能使用private? ——使用private修饰抽象方法后,这个抽象方法只能在本类使用,其他类不能实现它
//2)为什么不能使用final? ——使用final修饰抽象方法后,该方法不能被重写
//3)为什么不能使用static? ——抽象类不能被实例化,而且静态方法在类加载的时候就加载了,已经分配好了内存空间,
//  抽象类的抽象方法是需要被继承的子类进行重写的

 

5.抽象类最佳实践 —— 模板设计模式

1)什么是模板设计模式?

——定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤

2)模板设计模式的优点

——编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其他子类实现(实现了代码的复用)

3)一个小case快速了解模板设计模式

public class Test {
    public static void main(String[] args) {
        Calculate calculate = new Calculate();
        calculate.getDistance();//调用
    }
}

abstract class Pattern {
    //抽象方法
    public abstract void cal();

    public void getDistance() {
        long start = System.currentTimeMillis();
        cal();//存在动态绑定机制
        long end = System.currentTimeMillis();

        System.out.println("计算的时间是:" + (end - start));
    }
}

class Calculate extends Pattern {
    //重写了父类的抽象方法
    public void cal() {
        long sum = 0;

        for (int i = 0; i < 10000000; i++) {
            sum += i;
        }
    }
}

 

 

三.接口

1.什么是接口?

——接口就是给出一些没有实现的方法,把这些方法封装到一起,当某个类要使用的时候,根据具体情况把这些方法写出来

 

2.接口的格式

interface 接口名 {

        属性

        抽象方法

}

interface Computer {
    int age = 10;
    void say();
}

 

3.类如何和接口完成对接?

class 类名 implements 接口 {

        类的属性;

        类的方法;

        必须实现接口的抽象方法;

}

interface Computer {
    int age = 10;
    void say();
}

//类实现接口
class Usb implements Computer {
    public void say() {
        System.out.println("hello~");
    }
}

 

4.接口的细节讨论及实现

1)接口不能实例化

public class Test {
    public static void main(String[] args) {
        //Person person = new Person();//接口不能实例化
    }
}

//接口不能实例化
interface Person {
    void say();
}

2)接口中方法都是抽象方法(除掉默认方法、静态方法),且这些抽象方法均是public的,接口中的抽象方法,不需要再写abstract

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

interface Computer {
    //public void connect();
    //abstract void connect();
    //抽象方法
    void connect();
    void listen();
    void keyBoard();

    //默认方法: 可以在接口中实现具体的方法体
    default void say() {
    }

    //静态方法: 可以在接口中实现具体的方法体
    static void sing() {
    }
}

3)普通类实现接口,必须把接口中的所有方法均实现

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

interface Computer {
    //抽象方法
    void connect();
    void keyBoard();
}

//普通类实现接口中的方法
class Laptop implements Computer {
    public void connect() {
        System.out.println("连接网络~");
    }
    
    public void keyBoard() {
        System.out.println("打字~");
    }
}

4)抽象类实现接口,可以不用实现接口中的方法

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

interface Computer {
    //抽象方法
    void connect();
    void keyBoard();
}

//抽象类可以不用实现接口中的方法
abstract class Honor implements Computer {
}

5)一个类可以同时实现多个接口,接口之间使用逗号隔开

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

interface Computer {
    //抽象方法
    void watch();
    void keyBoard();
}

interface Usb {
    void connect();
}

//一个类可以同时继承多个接口
class Laptop implements Computer,Usb {

    @Override
    public void watch() {
    }

    @Override
    public void keyBoard() {
    }

    @Override
    public void connect() {
    }
}

6)接口中的属性是public static final 修饰的,所以我们需要初始化

7)接口中的属性访问形式:接口名.属性名

public class Test {
    public static void main(String[] args) {
        //接口中的属性访问形式:接口名.属性名
        System.out.println(Computer.AGE);//18
    }
}

interface Computer {
    //接口中的属性是public static final 修饰的
    //public static final int age = 10;
    int AGE = 18;
}

8)接口不能继承其他的类,但是可以继承一个或多个接口,接口间逗号隔开

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

interface Computer {
    void watch();
}

interface Laptop {
    void listen();
}

//接口不能继承其他的类,但是可以继承接口
interface Phone extends Computer,Laptop {
}

9)接口的修饰符只能是pubic和默认,这点跟对类的修饰符是相同的

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

//默认接口
interface Computer {
    void watch();
}

//单开文件
//public接口
public interface Laptop {
}

 

5.继承和接口的区别

1)继承解决了代码的复用性和可维护性

2)接口设计好了各种规范,让其他类去实现这些规范(灵活性)

3)继承是拥有了父类的各种功能,而接口可以理解为对子类扩展功能,也可以理解为接口是对Java单继承机制的一种补充

 

6.接口的多态特性

public class Test {
    public static void main(String[] args) {
        //接口数组
        Computer[] computers = new Computer[2];
        //给数组里填充内容
        computers[0] = new Laptop();//向上转型
        computers[1] = new Phone();//向上转型

        print(computers);
    }

    private static void print(Computer[] computers) {
        for (int i = 0; i < computers.length; i++) {
            computers[i].listen();
            computers[i].watch();

            if (computers[i] instanceof Laptop) {
                ((Laptop) computers[i]).play();//向下转型
            } else if (computers[i] instanceof Phone) {
                ((Phone) computers[i]).game();
            } else {
                System.out.print("");
            }
        }
    }
}

//接口
interface Computer {
    void watch();
    void listen();
}

class Laptop implements Computer {
    @Override
    public void watch() {
        System.out.println("用电脑看视频~");
    }

    @Override
    public void listen() {
        System.out.println("用电脑听歌~");
    }

    //特有方法
    public void play() {
        System.out.println("开黑~");
    }
}

class Phone implements Computer {
    @Override
    public void watch() {
        System.out.println("使用手机刷抖音~");
    }

    @Override
    public void listen() {
        System.out.println("打开QQ音乐听歌~");
    }

    //特有方法
    public void game() {
        System.out.println("王者荣耀走起~");
    }
}

 

7.多态传递现象

public class Test {
    public static void main(String[] args) {
        //多态传递:Computer --> Usb --> Phone(实现)
        //编译类型:Computer  运行类型:Phone
        Computer phone = new Phone();
        phone.watch();
        phone.listen();
        //phone.connect();
        //为什么不能使用?
        //因为编译类型只会找属于本类的,而connect是Usb的方法,不是Computer的方法

        Usb phone1 = new Phone();
        phone1.listen();
        phone1.listen();
        phone1.connect();//为什么可以? 因为Usb继承了Computer接口
    }
}

interface Computer {
    void watch();
    void listen();
}

interface Usb extends Computer {
    void connect();
}

//要全部实现接口中的方法
class Phone implements Usb {

    @Override
    public void watch() {
        System.out.println("看电影~");
    }

    @Override
    public void listen() {
        System.out.println("听歌~");
    }

    @Override
    public void connect() {
        System.out.println("连接Usb~");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1155648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过shiro框架记录用户登录,登出及浏览器关闭日志

背景&#xff1a; 公司项目之前使用websocket记录用户登录登出日志及浏览器关闭记录用户登出日志&#xff0c;测试发现仍然存在问题&#xff0c; 问题一&#xff1a;当浏览器每次刷新时websocket其实是会断开重新连接的&#xff0c;因此刷新一下就触发记录登出的日志&#xff0…

41.排序练习题(王道2023数据结构第8章综合练习)

试题1&#xff08;王道8.3.3节综合练习2&#xff09;&#xff1a; 编写双向冒泡排序算法&#xff0c;在正反两个方向交替扫描。即第一趟把关键字最大的元素放在序列的最后面&#xff0c;第二趟把关键字最小的元素放在序列最前面&#xff0c;如此反复。 首先实现冒泡排序&…

FIFO 位宽转换

从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […

美国白宫发布总统令:鼓励AI以安全、可靠的方式发展

美国华盛顿时间10月30日&#xff0c;美国白宫官网发布了&#xff0c;关于发展安全、可靠和值得信赖的AI&#xff08;人工智能&#xff09;的拜登总统行政令。 白宫表示&#xff0c;该行政令为AI安全和保障制定了新标准&#xff0c;保护了用户的数据隐私&#xff0c;促进公平和…

英语——歌曲篇——only you

《only you》(只有你)赏析 很多人都听过The Platters(派特斯乐队)演唱的《only you》(只有你)这首歌曲&#xff0c;尤其是看过在周星驰和罗家英在《大话西游》里面演绎的"无厘头"版本后。 不过&#xff0c;又有几人知道&#xff0c;这首歌曲原来是经典浪漫影片《罗马…

C语言_常用数据类型地址的理解

常用基本数据类型&#xff1a; #include <stdio.h> #include <stdlib.h> #include <stdint.h>int main(){printf("基本数据类型:\n");printf("char: %d\n", sizeof(char));printf("int: %d\n", sizeof(int));printf("do…

1.6 基本安全设计准则

思维导图&#xff1a; 1.6 基本安全设计准则笔记 目标&#xff1a;理解和遵循一套广泛认可的安全设计准则&#xff0c;以指导保护机制的开发。 主要准则&#xff1a; 机制的经济性&#xff1a;安全机制应设计得简单、短小&#xff0c;便于测试和验证&#xff0c;减少漏洞和降…

linux系统的环境变量-搞清环境变量到底是什么

环境变量 引例环境变量常见的环境变量echoexportenvunsetset 通过代码获取环境变量使用第三个参数获取使用全局变量enviorn获取环境变量通过系统调用获取环境变量 环境变量具有全局属性main函数前两个参数的作用 引例 在linux系统中&#xff0c;我们使用ls命令&#xff0c;直接…

Python 算法高级篇:深度优先搜索和广度优先搜索的高级应用

Python 算法高级篇&#xff1a;深度优先搜索和广度优先搜索的高级应用 引言 1. 深度优先搜索&#xff08; DFS &#xff09;回顾2. 广度优先搜索&#xff08; BFS &#xff09;回顾3. 拓扑排序4. 连通性检测5. 最短路径问题6. 案例分析&#xff1a;社交网络分析7. 总结 引言 深…

剑指 Offer || 084.全排列||

题目 给定一个可包含重复数字的整数集合 nums &#xff0c;按任意顺序 返回它所有不重复的全排列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,2] 输出&#xff1a; [[1,1,2],[1,2,1],[2,1,1]]示例 2&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1…

【蓝桥杯选拔赛真题07】C++小球自由落体 青少年组蓝桥杯C++选拔赛真题 STEMA比赛真题解析

目录 C/C++小球自由落体 一、题目要求 1、编程实现 2、输入输出 二、算法分析

PostgreSQL在云端:部署、管理和扩展你的数据库

随着云计算技术的迅猛发展&#xff0c;将数据库迁移到云端已经成为许多企业的首选。而在众多数据库管理系统中&#xff0c;PostgreSQL因其稳定性、灵活性和可扩展性而成为了不少企业的首选之一。 部署PostgreSQL在云端 将PostgreSQL部署在云端是一个相对简单的过程。云服务提供…

IMX6ULL——GPIO

本章目的&#xff1a;使用GPIO点亮一个LED灯 1.LED原理 &#xff08;1&#xff09;LED类型&#xff1a;插脚LED&#xff1b;贴片LED。 &#xff08;2&#xff09;LED点亮电路 法一&#xff1a; 法二&#xff1a; 我们本章使用法二&#xff0c;使用IMX6ULL的GPIO引脚输出高低电…

Java架构师软件架构的演化和维护

目录 1 导学2 软件架构演化和定义3 面向对象软件架构演化4 软件架构演化方式的分类5 软件架构演化原则6 软件架构演化评估方法7 大型网站架构演化8 软件架构维护想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导学 2 软件架构演化和定义 软件架构的演化和维护就是对…

2023-2024-1高级语言程序设计第1次月考

7-1-1 计算摄氏温度 给定一个华氏温度F&#xff0c;本题要求编写程序&#xff0c;计算对应的摄氏温度C。计算公式&#xff1a;C5(F−32)/9。题目保证输入与输出均在整型范围内。 输入格式: 输入在一行中给出一个华氏温度。 输出格式: 在一行中按照格式“Celsius C”输出对…

软考系统架构师案例分析知识点整理

系统规划&#xff1a;包括系统项目的提出预可行性分析&#xff1b;系统方案的制定、评价和改进&#xff1b;新旧系统的分析和比较&#xff1b;现有软件、硬件和数据资源的有效利用&#xff1b; 软件架构设计&#xff1a;XML技术&#xff1b;基于架构的软件开发过程&#xff1b;…

【算法通关村第一关】链表经典问题

1.两个链表第一个公共子节点 1.这是一道经典的链表问题&#xff1a;输入两条链表&#xff0c;找出他们的第一个公共节点。 使用集合的方法&#xff1a; public ListNode findFirstCommonNodeBySet(ListNode headA,ListNode headB){Set<ListNode> set new HashSet<&g…

Linux服务器部署带Cplex的Java项目

Linux版Cplex安装 Cplex安装包 Cplex 22.1.0 Linux安装包 安装步骤 找到安装包的路径 [roothecs-327697 ~]# cd /www/cplex [roothecs-327697 cplex]# ls cplex_studio2210.linux_x86_64.bin使用chmod 777赋予安装包读、写、执行权限&#xff0c;使用./执行安装 [roothec…

数字IC前端学习笔记:数字乘法器的优化设计(基4布斯编码华莱士树乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 使用基2布斯乘法器虽然能减少乘数中0的数量&#xff0c;但最终还是无法减少部分积的数量&#xff0c;因此一种更合理的编码方式产生了——基4布斯编码。它可以将部…

LeetCode刷题---简单组(六)

文章目录 &#x1f352;题目一 69. x 的平方根&#x1f352;解法一&#x1f352;解法二&#x1f352;题目二 70. 爬楼梯&#x1f352;解法一 &#x1f352;题目一 69. x 的平方根 &#x1f352;解法一 class Solution(object):def mySqrt(self, x):""":type x:…