Java核心-面向对象(下)

之前说完了类、对象、方法以及面向对象的三大特性封装、继承和多态,现在来了解一下接口、代码块和一些常见的类如抽象类、包装类等。
在这里插入图片描述

一、接口

1、概念

接口(Interface),是一种抽象类型,是抽象方法的集合,是对功能的抽象。接口本身不包含任何实现细节,只是定义了一种规范,规定了实现接口的类应该做什么,而不是怎么做。在前面讲 java数据类型时也提到接口,是一种引用类型。

注:interface关键字声明接口,implements关键字实现接口。

接口定义一种规范,规定某一批类里必须提供某些方法,要求这些类必须完全实现接口里所定义的全部抽象方法,从而实现接口中定义的功能。

要访问接口方法,接口必须由另一个具有implements关键字(而不是 extends)的类"实现"(类似于继承)。接口方法的主体由"implement"类提供。

2、语法

定义一个接口的语法如下。

[修饰符] interface 接口名 extends 父接口1, 父接口2, ... {
    0-N 常量
    0-N 抽象方法
    0-N 内部类、接口、枚举
    0-N 默认方法或静态方法 // Java 8 以上才允许
}

3、几点注意

1)接口无法被实例化,但是可以被实现,可以多实现。一个类实现了一个或多个接口之后,这个类必须完全实现(重写)这些接口里所定义的全部抽象方法,否则该类必须定义成抽象类。
2)接口没有构造方法,不能包含成员变量,除static 和 final 变量。
3)接口支持多继承。(Java类是单继承)
4)实现接口语法如下

[修饰符] class 实现类名 extends 父类 implements 接口1, 接口2, ... {
}

接口与接口之间有继承关系extends,支持多继承

类与接口之间有实现关系implements,可以多实现

实现接口方法时,必须使用 public 修饰

接口的方法默认就是public abstract,故可省略不写

4、接口和抽象类

接口和类是两个不同的概念,其中,类描述对象的属性和方法,而接口则包含类要实现的方法。接口体现的是一种规范,抽象类体现的是一种模板式设计

5、总结

1)Java的接口(interface)定义了纯抽象规范,一个类可以实现多个接口;
2)接口也是数据类型,属于引用类型,适用于向上转型(upcasting)和向下转型(downcasting);
3)接口的所有方法都是抽象方法,接口不能定义实例字段;
4)接口可以定义default方法(JDK>=1.8)

6、面向接口编程(扩展)

面向接口编程是一种编程范式,强调的是在设计软件应用时,应该先定义接口,再实现接口。这种方式有很多优点,如可以提高代码的可读性、可维护性和可扩展性,以及降低代码之间的耦合度。

1)接口多态声明方式

// 接口名 变量名 = new 该接口的实现类名();
// 面向接口编程
Animal myDog=new Dog();

2)简单案例
首先定义一个Animal接口,并在接口内定义eat和sleep方法。

public interface Animal {
    // 定义一个接口
    void eat(); // 接口的方法默认就是public abstract,故可省略
    void sleep();
}

再定义一个Dog类,用该类实现Animal接口,并在main方法中使用接口类型的引用myDog来调用eat和sleep方法。

public class Dog implements Animal {
    // 重写Animal接口内所定义的全部抽象方法
    @Override
    public void eat() {
        System.out.println("Dog is eating");
    }
    @Override
    public void sleep() {
        System.out.println("Dog is sleeping");
    }
    // 在主函数中使用接口类型的引用来调用方法
    public static void main(String[] args) {
        // 接口名 变量名 = new 该接口的实现类名();
        // 面向接口编程
        Animal myDog=new Dog();
        myDog.eat();
        myDog.sleep();
    }
}

运行结果

Dog is eating
Dog is sleeping

分析

使用面向接口编程的好处就是,可以轻松地更换实现接口的类,而不需要修改使用接口的代码。例如,我们可以定义一个新的类Cat,这个类也实现了Animal接口,然后我们可以在不修改主函数的情况下,将myDog的引用更换为Cat的实例。这就是面向接口编程的基本思想:编程针对接口,而不是针对实现。这样可以使我们的代码更加灵活和可扩展,也更容易进行单元测试和重构。

二、代码块

代码块里的变量属于局部变量,只在自己所在区域(即前后的 {})内有效。

1、局部代码块

直接定义在方法内部的代码块,如条件执行体、循环体。

2、普通初始化块

即构造代码块:直接定义在类中(一般不这么用)。

3、静态代码块

即类初始化块:初始化块的修饰符只能是 static。使用 static 修饰的初始化块,通常用来对类变量做初始化操作、加载资源、加载配置文件等。

  • 随着所在类的加载而执行(只执行一次)。
  • 在同类中优先于 main 方法执行。

4、案例

1)编写一个程序示例如下

public class Demo {
    private static Demo demo=new Demo(); // 单例模式
    static {
        System.out.println("静态初始化");  //静态代码块=>static修饰
    }
    Demo(){
        // 编译后,“还原”到这里 System.out.println("普通初始化块");
        System.out.println("构造器...");
    }
    {
        System.out.println("普通初始化块");  //普通初始化块=>直接定义在类中
    }
    public static void main(String[] args) { //局部代码块=>直接定义在方法内部
        System.out.println("进入 main 方法");
        new Demo();
        new Demo();
    }
}

2)程序执行结果为

普通初始化块
构造器...
静态初始化
进入 main 方法
普通初始化块
构造器...
普通初始化块
构造器...

3)结果分析
代码执行顺序:父类静态代码块 -> 子类静态代码块 -> 父类非静态代码块 -> 父类构造方法 -> 子类非静态代码块 -> 子类构造方法

  • 类变量的初始化 及 静态初始化块(执行顺序与它们在源代码中的排列顺序相同)
  • 实例变量的初始化 及 普通初始化块(执行顺序与它们在源代码中的排列顺序相同)
  • 构造器(先加载父类的字节码文件并调用父类的构造器)
  • main 方法

三、一些类

1、内部类(Inner Classes)

说到类与类之间的关系,很多人首先想到的可能是并列关系,其实还有嵌套关系,比如内部类。顾名思义,内部类就是一个类定义在另一个类的内部。内部类可以分为以下几种。

注:包含内部类的最外面那个类称为外部类(outer class)

1.1 成员内部类

1)成员内部类是最普通的内部类,位于另一个类的内部。

class Circle { //外部类
    double radius=0; //成员变量
    public Circle(double radius){ //成员方法
        this.radius=radius;
    }
    class Draw{ //成员内部类
        public void drawShape(){
            System.out.println("drawshape");
        }
    }
}

2)成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

class Circle { //外部类
    private double radius = 0; //成员变量
    public static int count =1; //静态成员
    public Circle(double radius) { //成员方法
        this.radius = radius;
    }
    class Draw {     //成员内部类
        public void drawShape() {
            System.out.println(radius); //外部类的private成员
            System.out.println(count);  //外部类的静态成员
        }
    }
}

3)当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问。

外部类.this.成员变量
外部类.this.成员方法

4)外部类如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问

public class Circle { // 外部类
    private double radius = 0;
    public Circle(double radius) {
        this.radius = radius;
        getDrawInstance().drawShape();   //必须先创建成员内部类的对象,再进行访问
    }  //Draw d=new Draw(),上面代码相当于d.drawShape(),因为getDrawInstance()方法返回了Draw对象
    private Draw getDrawInstance() {
        return new Draw();  //返回成员内部类的对象
    }
    class Draw {     //成员内部类
        public void drawShape() {
            System.out.println(radius);  //外部类的private成员
        }
    }
    public static void main(String[] args) {
        Circle c=new Circle(1);
    }
}
// 输出结果:1.0

5)成员内部类是依附外部类而存在的,即如果要创建成员内部类的对象,必须先存在一个外部类的对象。创建成员内部类对象的两种方式如下。

  • 通过外部类对象创建
  • 通过getInstance方法创建
public class Test {
    public static void main(String[] args)  {
        Outter outter = new Outter(); //第一种方式
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
        Outter.Inner inner1 = outter.getInnerInstance(); //第二种方式,getInstance方法
    }
}
class Outter { // 外部类
    private Inner inner = null;
    public Outter() { //无参构造
    }
    public Inner getInnerInstance() { //getInnerInstance()方法
        if(inner == null)
            inner = new Inner();
        return inner;
    }
    class Inner { // 成员内部类
            public Inner() { //无参构造
        }
    }
}

注:getInstance在单例模式 (保证一个类仅有一个实例,并提供一个访问它的全局访问点) 的类中常见,用来生成唯一的实例,getInstance往往是static的。

1.2 局部内部类

概念:定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内

作用域:即一个变量或方法在程序中可以被访问的范围,可以是一个类、方法或一个代码块。

局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。eg:

class People{
    public People() { // 无参构造
    }
}
class Man{
    public Man(){ // 无参构造
    }
    public People getWoman(){
        class Woman extends People{   //局部内部类,定义在getWoman这个方法内
            int age =0;
        }
        return new Woman();
    }
}
1.3 匿名内部类

匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类。

注:在编写事件监听代码时使用匿名内部类不但方便,而且使代码更加容易维护。

1.语法

new <类或接口>() {
    // 类的主体
};

优点:这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。使用匿名类可使代码更加简洁、紧凑,模块化程度更高。

2.匿名类的两种实现方式
1)继承一个类,重写其方法。
2)实现一个接口(可以是多个),实现其方法。

注:匿名内部类实现一个接口的方式与实现一个类的方式相同

3.案例

public class Out {
    void show(){
        System.out.println("调用 Out 类的 show() 方法");
    }
}
class testAnonyInter { // 测试
    private void show() {
        // 在这个方法中构造一个匿名内部类
        Out anonyInter = new Out() {
            // 获取匿名内部类的实例
            void show() {
                System.out.println("调用匿名类中的 show() 方法");
            }
        };
        anonyInter.show();
    }
    public static void main(String[] args) {
        testAnonyInter tA = new testAnonyInter();
        tA.show();
    }
}

运行结果

调用匿名类中的 show() 方法

4.匿名类的特点
1)匿名类和局部内部类一样,可以访问外部类的所有成员。eg:

public class Out {
    void show(){
        System.out.println("调用 Out 类的 show() 方法");
    }
}
class testAnonyInter {
    public static void main(String[] args) {
        int a = 10;
        final int b = 10;
        Out anonyInter = new Out() { // 构造一个匿名类
            void show() {
                System.out.println("调用了匿名类的 show() 方法"+a);    // 编译出错
                System.out.println("调用了匿名类的 show() 方法"+b);    // 编译通过
            }
        };
        anonyInter.show();
    }
}

运行结果

调用了匿名类的 show() 方法10
调用了匿名类的 show() 方法10

2)匿名类中允许使用非静态代码块进行成员初始化操作。eg:

Out anonyInter = new Out() {
    int i; {    // 非静态代码块
        i = 10;    //成员初始化
    }
    public void show() {
        System.out.println("调用了匿名类的 show() 方法"+i);
    }
}

3)匿名类的非静态代码块会在父类的构造方法之后被执行。

5.补充

匿名内部类不能有访问修饰符和static修饰符。

匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

1.4 静态内部类

1)概念
定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
2)说明

静态内部类不需要依赖于外部类,这点和类的静态成员属性类似,并且它不能使用外部类的非static成员变量或者方法,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

3)eg:

public class Test { // 测试类
    public static void main(String[] args){
        Outter.Inner inner=new Outter.Inner();
    }
}
class Outter{
    int a=10;
    static int b=5;
    public Outter(){
    }
    static class Inner{ //静态内部类
        public Inner(){
            //System.out.println(a); 编译出错,java: 无法从静态上下文中引用非静态变量 a
            System.out.println(b); //输出结果:5
        }
    }
}

2、抽象类

2.1 抽象方法

1)概念
一个方法使用 abstract 来修饰,且只有声明没有实现
2)特征

  • 使用 abstract 修饰且没有方法体(没有方法体与空方法体不同)。
  • 抽象方法只能定义在抽象类或接口中。
  • 不能使用 private、final 或 static 修饰。

注:在使用 abstract 关键字修饰抽象方法时不能使用 private 修饰,因为抽象方法必须被子类重写,而如果使用了 private 声明,则子类是无法重写的。

2.2 抽象类

与抽象方法一样,抽象类也要使用 abstract 关键字声明。几点注意如下:

一个方法被声明为抽象的,那么这个类也必须声明为抽象的。一个抽象类中,可以有 0~n 个抽象方法和具体方法。

有构造方法,但不能直接用来创建对象,只留给子类创建对象时调用。

子类重写父类时,必须重写父类所有的抽象方法。即抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

抽象类不能实例化,即不能使用 new 关键字创建对象

要访问抽象类,它必须从另一个类继承

3)代码示例
创建一个抽象类 Shape

public abstract class Shape {
    public int width; // 几何图形的长
    public int height; // 几何图形的宽
    public Shape(int width, int height) { //带全部参数的构造方法
        this.width = width;
        this.height = height;
    }
    public abstract double area(); // 定义抽象方法,计算面积
}

定义一个正方形类Square,继承形状类 Shape,并重写了 area( ) 抽象方法。

public class Square extends Shape {
    public Square(int width, int height) {  //带全部参数的构造方法
        super(width, height);
    }
    // 重写父类中的抽象方法,实现计算正方形面积的功能
    @Override
    public double area() {
        return width * height;
    }
}

再定义一个三角形类Triangle,继承形状类 Shape,并重写父类中的抽象方法 area()。

public class Triangle extends Shape {
    public Triangle(int width, int height) {  //带全部参数的构造方法
        super(width, height);
    }
    // 重写父类中的抽象方法,实现计算三角形面积的功能
    @Override
    public double area() {
        return 0.5 * width * height;
    }
}

最后创建一个测试类。

public class ShapeTest {
    public static void main(String[] args) {
        Square s = new Square(5, 4); // 创建正方形类对象
        System.out.println("正方形的面积为:" + s.area());
        Triangle t = new Triangle(2, 5); // 创建三角形类对象
        System.out.println("三角形的面积为:" + t.area());
    }
}

运行结果

正方形的面积为:20.0
三角形的面积为:5.0

总结:Shape 类只是定义了计算图形面积的方法,而对于如何计算并没有任何限制,需要子类重写父类抽象方法来具体实现。即抽象类 Shape 仅定义了子类的一般形式,所以是抽象的

3、基本类型包装类

1)装箱
基本类型数据转成对应的包装类对象
2)拆箱
包装类对象转成对应的基本类型数据
3)自动装箱
把一个基本类型变量直接赋给对应的包装类变量或 Object 变量

  • 在底层依然是手动装箱,使用的是 Xxx.valueOf() 方法

4)自动拆箱
包装类对象直接赋给对应的基本类型变量,或者包装类对象与基本数据类型变量使用“==”比较

  • 在底层依然是手动拆箱,使用的是 xxxValue() 方法

注:八大基本数据类型的包装类都是最终类、不可变类(对应的储存数值的成员变量 value 值使用 private final 修饰)

5)对应
在这里插入图片描述

Byte、Short、Integer、Long、Float、Double、BigDecimal、BigInteger 类都是 Number 抽象类的子类,都是 Comparable 接口的实现类

6)案例

public class Test {
    public static void main(String[] args) {
        // 装箱
        Integer intObj1 = new Integer(123);
        Integer intObj2 = Integer.valueOf(123); // 推荐,带有缓存
        // 拆箱
        int num3 = intObj1.intValue(); // int num3 = new Integer(123);
        Integer intObj4 = 123;  // 底层 Integer intObj4 = Integer.valueOf(123)
        int num5 = intObj4; // 底层 int num5 = intObj4.intValue()
        boolean b = intObj4 == 123;// true,底层 intObj4.intValue() == 123
        Object boolObj = true;
        if (boolObj instanceof Boolean) {
            boolean b1 = (Boolean)boolObj; // 大转小(Object->boolean),强转
            System.out.println(b1);
        }
    }
}
// 结果:true

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年2月12日-2月18日周报

文章目录 1. 本周计划2. 完成情况2.1 论文摘要2.2 数据集2.3 基准测试 3. 总结及收获4. 下周计划 1. 本周计划 阅读论文《 E F W I E^{FWI} EFWI: Multiparameter Benchmark Datasets for Elastic Full Waveform Inversion of Geophysical Properties》 了解一种新型的数据集&…

阿里云OSS和SEC服务器,免费ssl证书申请和安装

一&#xff1a;阿里云OSS证书申请和安装 1创建免费证书等待签发 2验证&#xff0c;复制DNS解析配置 3在主体域名中解析DNS&#xff08;记录复制上面的证书申请配置&#xff09; 4验证域名DNS配置 5下载证书 6安装OSS证书 7上传证书&#xff08;下载的证书解压&#xff09…

【Java中23种设计模式-单例模式2--懒汉式2线程安全】

加油&#xff0c;新时代打工人&#xff01; 简单粗暴&#xff0c;学习Java设计模式。 23种设计模式定义介绍 Java中23种设计模式-单例模式 Java中23种设计模式-单例模式2–懒汉式线程不安全 package mode;/*** author wenhao* date 2024/02/19 09:38* description 单例模式…

vmware-17虚拟机安装教程及版本密钥(保姆级,包含图文讲解,不需注册账户)

文章目录 vmware安装教程一、下载vmware二、安装三、破解密匙 vmware安装教程 一、下载vmware 1.进入VMware官网&#xff1a;https://www.vmware.com/sg/products/workstation-pro.html 2.向下翻找到&#xff0c;如下界面并点击“现在安装” 3.稍事等待以下直到出现以下界面…

【知识整理】简述 Code Review - 代码审查

一、Code Review 简述 为保证上线代码质量&#xff0c;经研究决定0412版本起实行Code Review 。具体操作方式为组织 review 会。提出的优化点需立即执行更改&#xff0c;Review会要求给出调整方式方法。同时为了确保项目或迭代版本的时间&#xff0c;请各开发同学提前做好时间…

【EI会议征稿通知】第五届电子通讯与人工智能国际学术会议(ICECAI 2024)

第五届电子通讯与人工智能国际学术会议&#xff08;ICECAI 2024&#xff09; 2024 5th International Conference on Electronic communication and Artificial Intelligence 第五届电子通讯与人工智能国际学术会议&#xff08;ICECAI 2024&#xff09;将于2024年5月31日-6月…

Linux小程序--进度条

目录 1.知识补充 1.1回车和换行 1.2缓冲区 2.实现倒计时 3.实现进度条 1.知识补充 1.在制作小程序进度条之前&#xff0c;我们先了解一下&#xff0c;回车换行和行缓冲区的概念。 2.动态效果&#xff0c;在同一个位置刷新不同的图像&#xff0c;实现一个倒计时的效果。…

【Flink状态管理(八)】Checkpoint:CheckpointBarrier对齐后Checkpoint完成、通知

文章目录 一. 调用StreamTask执行Checkpoint操作1. 执行Checkpoint总体代码流程1.1. StreamTask.checkpointState()1.2. executeCheckpointing1.3. 将算子中的状态快照操作封装在OperatorSnapshotFutures中1.4. 算子状态进行快照1.5. 状态数据快照持久化 二. CheckpointCoordin…

什么是伪数组 以及伪数组转真数组的方法

什么是伪数组呢&#xff1f; 1.我们先来看看用于接受实参的方法 arguments , 执行代码如下&#xff1a; function fn() { console.log(arguments);}fn(1,2,3,4,5) 这里可以看到&#xff0c;Arguments显示的也有方括号 [1,2,3,4,5...] &#xff0c;但是后面多了一些其他方法&a…

c++类和对象新手保姆级上手教学(中)

前言&#xff1a; 类和对象中篇&#xff0c;这里讲到的前4个默认成员函数&#xff0c;是类和对象中的重难点&#xff0c;许多资料上的讲法都非常抽象&#xff0c;难以理解&#xff0c;所以我作出这篇总结&#xff0c;分享学习经验&#xff0c;以便日后复习。 目录 6个默认成员…

新算法UoT助力AI提问——主动寻求信息,任务完成率提高57.8%

引言&#xff1a;信息寻求在不确定性环境中的重要性 在不确定性环境中&#xff0c;信息寻求的能力至关重要。在许多实际应用中&#xff0c;如医学诊断和故障排除&#xff0c;解决任务所需的信息并非一开始就给出&#xff0c;而需要通过提问后续问题来主动寻求&#xff08;例如…

MobaXterm的SFTP文件上传/下载

一、MobaXterm的简介 MobaXterm是一款功能强大的远程计算工具&#xff0c;集成了诸多网络工具和便利功能&#xff0c;包括SSH、X11服务器、SFTP等&#xff0c;支持Windows系统。用户可以使用MobaXterm来轻松管理远程服务器&#xff0c;进行文件传输&#xff0c;远程桌面显示等操…

Rocky 8.9 Kubespray v2.24.0 在线部署 kubernetes v1.28.6 集群

文章目录 1. 简介2. 预备条件3. 基础配置3.1 配置hostname3.2 配置互信 4. 配置部署环境4.1 在线安装docker4.2 启动容器 kubespray4.3 编写 inventory.ini4.4 关闭防火墙、swap、selinux4.5 配置内核模块 5. 部署 1. 简介 kubespray​ 是一个用于部署和管理 Kubernetes 集群的…

掌握array_walk()函数:解锁PHP数组操作的神奇力量!

掌握array_walk()函数&#xff1a;解锁PHP数组操作的神奇力量&#xff01; 在 PHP 开发过程中&#xff0c;我们经常需要对数组进行遍历和处理。array_walk() 函数是 PHP 函数库中的一个重要工具&#xff0c;它提供了一种便捷的方式来对数组中的每个元素执行自定义操作。本文将深…

【EI会议征稿通知】2024年第四届计算机视觉与模式分析国际学术大会(ICCPA 2024)

2024年第四届计算机视觉与模式分析国际学术大会&#xff08;ICCPA 2024&#xff09; 2024 4th International Conference on Computer Vision and Pattern Analysis (ICCPA 2024) 第四届计算机视觉与模式分析国际会议&#xff08;ICCPA 2024&#xff09;将于2024年5月17日至1…

Unity编辑器扩展之是否勾选Text组件BestFit选项工具(此篇教程也可以操作其他组件的属性)

想要批量化是否勾选项目预制体资源中Text组件BestFit属性&#xff08;此篇教程也可以操作其他组件的属性&#xff0c;只不过需要修改其中对应的代码&#xff09;&#xff0c;可以采用以下步骤。 1、在项目的Editor文件中&#xff0c;新建一个名为TextBestFitBatchProcessor的…

忘记管理员密码

1、在/home/jenkins/config.xml中删除&#xff1a; <useSecurity>true</useSecurity><authorizationStrategy class"hudson.security.FullControlOnceLoggedInAuthorizationStrategy"><denyAnonymousReadAccess>false</denyAnonymousRea…

html+css+jquery实现轮播图自动切换、左右切换、点击切换

pc端也好、移动端也好&#xff0c;轮播图很常见&#xff0c;今天用htmlcssjquery实现小米商城轮播图&#xff0c;套UI框架更容易实现 步骤1&#xff1a;把静态轮播图用divcss布局出来&#xff0c;采用盒子模型、相对绝对定位实现 代码如下&#xff1a; <!doctype html>…

leetcode:无重复字符的最长字串(详解)

文章目录 一、题目描述&#xff1f;二、题解方案一&#xff1a;容易理解&#xff08;时间复杂度O(n)&#xff09;方案二&#xff1a;滑动窗口&#xff08;时间复杂度O(n)&#xff09; 一、题目描述&#xff1f; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最…

十二:枚举与注解

文章目录 01、枚举类的使用1.1、枚举类的理解1.2、自定义枚举类1.3、使用enum关键字定义枚举类1.4、Enum类中的常用方法1.5、使用enum关键字定义的枚举类实现接口 02、注解的使用2.1、注解的理解2.3、如何自定义注解2.4、jdk中4个基本的元注解的使用12.5、jdk中4个基本的元注解…