首页 > 编程语言 >Java笔记(抽象类、接口、内部类、final关键字)

Java笔记(抽象类、接口、内部类、final关键字)

时间:2024-12-19 13:27:41浏览次数:10  
标签:Java 重写 void 接口 public 抽象类 方法 final

Java笔记(抽象类、接口、内部类、final关键字)

(一).抽象类

  • 抽象方法所在的类就是抽象类,抽象方法是在public和void中间加一个abstract,表示子类继承父类(父类是抽象类 )的方法时必须重写,否则直接报错
1.抽象方法和抽象类

2.抽象类和抽象方法的定义格式

3.抽象类和抽象方法的注意事项

image-20221121163721749

  • 不能实例化就是不能创建对象,抽象类是用来继承的

  • 抽象类的构造方法是创建子类对象时给属性进行赋值的image-20221121170654680

  • 针对,每个私有化的成员变量,要提供对应的get和set方法

  • 为什么非要把相同的东西调用到父类里面的原因:就是为了统一代码image-20221121173642818

4.抽象总结

image-20221121173851485

(二).接口

1.接口的定义和使用

image-20221121180832934

image-20221123145828834

  • 创建接口的实现类对象之后要重写方法
2.接口中成员的特点
  • 成员变量
    • 只能是常量(成员变量),必须使用public final static三个关键词修饰
    • 默认修饰符:public static final,默认的意思是就算没写,JAVA也会自动帮加上
      • 因为多个子类的共有属性是抽取到父类里面的,不会抽取到接口里面,所以接口里面是不会有类似name,age这些成员变量的,而且接口是一种规则,规则是不能改变的,所以接口里面的量都是常量,会用final修饰
      • static是为了调用,调用时直接 接口名点常量名称
      • public公共的,在所有地方都能使用接口里的常量
  • 构造方法
    • 没有:因为接口里不能创建对象,而且接口也不需要给子类的成员变量去赋值
  • 成员方法
    • 只能是抽象方法(JDK7以前:接口中只能定义抽象方法)
    • 默认修饰符:public abstract
3.接口和类的关系
1.)类和类的关系
  • 继承关系,只能单继承,不能多继承,但是可以多层继承
2.)类和接口的关系
  • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 多个接口中如果有同名的方法,在子类中重写时系统也只会提示一种,所以不用全部重写,接口只是告诉有这个方法,想要用方法需要自己重写image-20221121201957943
3.)接口和接口的关系
  • 继承关系,可以单继承,也可以多继承,如果是实现类实现的是最下面的子接口的话,那么需要重写所有的抽象方法
  • 下图中例子:接口三继承了接口一和接口二,新建一个实现类实现接口三,那么需要把接口一二三中所有的抽象方法都重写,如果少写一个,代码会报错image-20221121202459652
4.JDK8开始接口中新增的方法
1.)接口中可以定义默认方法

image-20221122075150845

image-20221122075426944

  • 接口中的抽象方法注意事项

    • 默认方法指的是前面有default,default也是他的关键字

    • package interfaceDemo03;
      //接口类
      public interface inter {
         //定义一个抽象方法,注意抽象方法没有方法体
          public abstract void method();
      
          //写一个默认方法
          //默认方法不是抽象方法,所以在实现类中不强制重写,但是如果被重写,需要去掉default关键字
          
      //default不能省略,因为不加default系统默认接口中的方法是抽象方法,那么抽象方法不能有方法体
          //注意加了default后变成接口中的抽象方法就可以有方法体
          public default void show(){
              System.out.println("接口中的默认方法----show");
      
      
          }
      
      
      
      }
      
      
    • package interfaceDemo03;
      //实现类
      public class interimpl implements inter{
      //以下为重写接口中的抽象方法,重写时idea也只会默认提示重写抽象方法
          @Override
          public void method() {
              System.out.println("实现类重写的抽象方法");
          }
      
      
      
      //在实现类中 重写默认方法(default),需要去掉public和void中间的关键字(default),加上就会报错
          @Override
          public void show() {
              System.out.println("重写接口类中的默认方法");
          }
      }
      
      
    • package interfaceDemo03;
      //测试类
      public class Test {
          public static void main(String[] args) {
      
      
              //创建实现类intermpl的对象
              interimpl ii = new interimpl();
              //调用接口中的抽象方法(已在interimpl类中重写抽象方法)
              ii.method();
              //调用接口中的默认方法(没有在interimpl类中重写该默认方法)
              ii.show();
          }
      }
      
      
2.)接口中可以定义静态方法

image-20221122082931970

  • 子类把从父类继承下来的虚方法表里的方法覆盖了这才叫做重写
3.)接口中可以定义私有方法

image-20221122084314295

  • 下面第一种是给默认方法服务的(注意中间没有default修饰 )
  • 下面第二种是给静态方法服务的
  • 不同类型的私有方法(可以抽取本类方法中相同方法到一个不想让外界访问的私有方法中)只能去服务不同类型的方法

image-20221122084536088

package interfaceDemo05;
//定义一个接口A
public interface InterA {
    public default void show1(){
        System.out.println("show1方法开始执行了");
        show3();
    }
    public default void show2(){
        System.out.println("show2方法开始执行了");
        show3();
    }
    //定义一个不想让外界访问的show3方法
    //中间没有加default
    //普通的私有方法,给默认方法去服务
    private void show3(){
        System.out.println("记录程序日志");

    }



}

package interfaceDemo05;
//定义一个接口B
public interface InterB {
 
    public static void show3() {
        System.out.println("show3方法开始执行了");
        show5();
    }

    public static void show4() {
        System.out.println("show4方法开始执行了");
        show5();
    }

    //定义一个不想让外界访问的show5方法
    //中间没有加default
    //普通的私有方法,给静态方法去服务
    private static void show5() {
        System.out.println("记录程序日志");

    }

}

image-20221122090215358

5.接口的应用

如果一个方法中的参数是一个接口,那么在调用这个方法时候就可以传递这个接口所有的实现类对象

编译看左边运行看右边

image-20221122091044513

image-20221122091114650

6.适配器设计模式

image-20221122092409629

  • 当一个接口中抽象方法过多,但是我只使用其中一部分时候,就可以用适配器设计模式

  • package interfaceDemo06;
    //定义一个有很多抽象方法的接口
    public interface Inter {
        public abstract void method1();
        public abstract void method2();
        public abstract void method3();
        public abstract void method4();
        public abstract void method5();
        public abstract void method6();
        public abstract void method7();
        public abstract void method8();
        public abstract void method9();
        public abstract void method10();
    }
    
    
  • package interfaceDemo06;
    //定义一个适配器
    public abstract class InterAdapter implements Inter{
    //对接口里的所有方法先进行空实现,即没有方法体
        //因为适配器中的方法都是空实现,创建适配器的对象没有意义,所以一般把接口定义成abstrac,防止外界创建适配器的对象
    //让适配器实现接口,让子类继承适配器
        @Override
        public void method1() {
    
        }
    
        @Override
        public void method2() {
    
        }
    
        @Override
        public void method3() {
    
        }
    
        @Override
        public void method4() {
    
        }
    
        @Override
        public void method5() {
    
        }
    
        @Override
        public void method6() {
    
        }
    
        @Override
        public void method7() {
    
        }
    
        @Override
        public void method8() {
    
        }
    
        @Override
        public void method9() {
    
        }
    
        @Override
        public void method10() {
    
        }
    }
    
    
  • package interfaceDemo06;
    
    public class interimpl extends InterAdapter{
        //定义好适配器后,就不需要实现接口,直接继承中间的interadapter
        //那么在这个类中,需要用到哪个方法,就重写哪个方法
        //也就是说给接口设置了一个适配器,只让子类去重写利用特定的方法
    
    
        @Override
        public void method5() {
            System.out.println("只用了第五个方法");
        }
    }
    
    
  • package interfaceDemo06;
    //测试类
    public class Test{
    
        public static void main(String[] args) {
    //想要测试方法,需要先new一个类的对象,再用对象调用这个类的方法
            interimpl s = new interimpl();
            s.method5();
        }
    }
    
    
  • 如果实现类还有爹,那么让中间类(适配器)继承这个爹,实现类继承中间类(适配器)即可

    • 实现类–中间类–父类

(三).内部类

  • 初识内部类

image-20221122101516878

可以在外部其他类中定义内部类,并调用内部类的方法

image-20221122101842270

注意右边注释

  • 外部类的对象创建需要在主函数中
  • 内部类的创建对象在外部类中

image-20221122103632839

image-20221122104251295
1.成员内部类
1.)成员内部类如何书写

image-20221122105051346

  • private修饰内部类后只能在外部类中使用,创建内部类的对象在内部类之外,外部类之内,一单私有,那么不能在其他类创建对象
  • 前面什么都不写就和成员变量一样,就是默认权限,只能在本包(pckage)中使用
  • protected是在本包中和其他包的子类中使用
  • public表示可以在其他任何地方创建内部类的对象
  • static修饰,表示静态内部类
2.)如何创建成员内部类的对象

image-20221122105621516

Outer.Inner oi = new Outer().new Inner;
//用外部类变量去调用内部类变量,把地址赋给oi
//链式编程
//Sout(new Outer().name)
  • 内部类被private修饰,那么在外界就不能直接创建内部类的对象
    • 第一种解决方法:把private改成public
      • 第二种解决方法:在外部类中定义一个提供内部类的方法,方法当中返回内部类成员,外界直接通过方法去获得内部类的对象image-20221122114545469
3.)成员内部类如何获取外部类的成员变量
public class outer{
    private int a =10;
	class Inner{
    private int a 20;
	public void show(){
	int a 30;
	System.out.println(Outer.this.a);//注意此处调用外部类成员变量的方法 Outer.this.a
	System.out.println(this.a);//调用内部类方法外的成员变量
	System.out.println(a);//就近原则,调用方法内部的成员变量
		}
	}      
}

public class Test{
    public static void main(string[]args){
		//创建内部类的对象,并调用show方法
	Outer.Inner oi new outer().new Inner();
	oi.show();
	}
    
}

image-20221123100840362

  • 内部类对象里面有一个 Outer this用来记录外部类对象的地址,Outer.this.a取得就是外部类对象的值

image-20221123101307518

  • 上述第四点是访问外部类的成员变量
2.静态内部类
  • 成员内部类的一种特殊情况

  • 当成员内部类前面用static修饰时,这个类就成为了静态内部类

  • 因为是静态,所以不用创建键外部类的对象,直接用外部类的类名就可以直接调用image-20221123103012150

  • 注意下图:静态类的静态方法中直接打印外部类的成员变量,不需要创建对象,直接打印即可;而静态类的静态方法中打印外部类的非静态变量,需要先在静态方法中创建外部类的对象,再用对象点上外部类的成员变量才能打印

  • image-20221123111910159

  • 创建静态内部类的变量

  • 只要是静态的东西,都可以用类名点直接获取(new Outer.Inner)

  • 以下为oi直接调用静态类中的非静态方法

  • 以下为调用静态类的静态方法的过程,一路点到底

  • 当然调用静态方法时可以直接用创建的oi调用show2,但idea不会提示,因为idea不建议image-20221123112742750

image-20221123113757449

3.局部内部类

1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
2.外界是无法直接使用,需要==在方法内部创建局部内部类的对象==并使用。
3.该类可以直接访问外部类的成员,也 可以访问方法内的局部变量。

  • 注意private public 默认 final只能修饰成员变量(成员变量是定义在类里面的变量),不能修饰局部变量(局部变量是定义在方法里面的变量

  • image-20221123115103332

  • 总结包含关系就是 外部类—(外部类的方法中的类)局部内部类

  • 局部内部类(Inner)里面有局部变量(name、age),外部类有成员变量(b,Inner类),局部内部类(Inner)可以直接访问(自己局部内部类的)局部变量(name、age)和(外部类的)成员变量(b),如果想访问自己(局部内部类)的变量(name、age),需要在自己外面,自己的方法里面创建自己的对象(i),再在方法里面,自己外面调用的局部变量(i.name、i.age)

4.匿名内部类

image-20221123140758400

  • 实现关系:Swim是一个接口,后面大括号里面对他是实现关系,而不是继承关系,后面紫色大圆圈圈起来的部分就是匿名内部类,注意后大括号后面的分号;

  • 方法的重写:后面匿名内部类实现了接口swim,实现接口就要重写接口里面的所有方法;

  • 创建对象:new关键字创建的就是后面大括号里面的内容;

  • Swim后面的小括号表示用的是没有参数的空参构造去创建的

  • 整体其实是new出来的对象,正真的匿名内部类是后面大括号的一堆

image-20221123141514232

  • Animal是一个类,匿名内部类对它是继承关系,而不是实现关系。
  • 方法的重写:既然是继承关系那么就要重写父类里的所有方法。
  • 创建对象:new创建了大括号里的对象
  • 整体其实是new出来的对象,正真的匿名内部类是后面大括号的一堆

image-20221123143701938

  • 如果类只使用一次,那么就不应该去专门定义一个类而且去创建一个这个类的对象,只需要用匿名内部类去当做参数传递给函数即可,如上图,把创建的匿名内部类对象当做method函数的参数传递进去,就相当于实现了多态

  • 拓展,既然整体相当于一个对象(这个对象是大括号的匿名内部类的对象),那么就可以把他(这个new的整体可以理解为Swim接口的实现类对象)赋值给Swim类型的变量,或者用这个对象调用方法(这个对象就是后面大括号创建的对象,所以他可以自己类里面的方法去实现自己类中的方法)image-20221123144334243

  • 链接:接口创建实现类对象(重写了接口中的方法)(接口多态)

image-20221123150423904

在实际开发中,我们常常遇到这样的情况:一个接口/类的方法的某个实现方式在程序中只会执行一次,但为了使用它,我们需要创建它的实现类/子类去实现/重写。此时可以使用匿名内部类的方式,可以无需创建新的类,减少代码冗余

//匿名内部类可以用在具体类、抽象类、接口上,且对方法个数没有要求。

//举例说明:设存在具体类Class01,抽象类AbstractClass01,接口Interface01
//具体类
public class Class01 {
    public void show(String s){
        System.out.println("啦啦啦");
    }
}
//抽象类
public abstract class AbstractClass01 {
    abstract void show(String s);
}
//接口
//如果实现类Interface01Impl全程只使用一次,那么为了这一次的使用去创建一个类,未免太过麻烦。我们需要一个方式来帮助我们摆脱这个困境。匿名内部类则可以很好的解决这个问题。
//public interface Interface01 {
//    void show();
//}
//public class Interface01Impl implements Interface01{
//    @Override
//    public void show() {
//        System.out.println("I'm a impl class...");
//    }
//}


public interface Interface01 {
    void show(String s);
}

public class TestInner {
    public static void main(String[] args) {
        
        //重写具体类的方法
        new Class01(){
            @Override
            public void show(String s) {
                System.out.println("我是一个" + s);
            }
        }.show("具体类");

        //重写抽象类的抽象方法
        new AbstractClass01(){
            @Override
            void show(String s) {
                System.out.println("我是一个" + s);
            }
        }.show("抽象类");

        //实现接口的抽象方法
        new Interface01(){
            @Override
            public void show(String s) {
                System.out.println("我是一个" + s);
            }
        }.show("接口");


    }
}

(四).final关键字

1.final关键字的使用

Java中声明类、属性和方法时,可使用关键字final来修饰。

  • final标记的类不能被继承。
  • final标记的方法不能被子类复写。
  • final标记的变量(成员变量或局部变量)即为常量,只能赋值一次。
2.final关键字修饰类、成员变量和成员方法

1.)final

final用来修饰一个类,意味着该类成为不能被继承的最终类。出于安全性的原因和效率上的考虑,有时候需要防止一个类被继承。例如,Java类库中的String类,它对编译器和解释器的正常运行有着很重要的作用,不能轻易改变它,因此把它修饰为final类,使它不能被继承,这就保证了String类的惟一性。同时,如果你认为一个类的定义己经很完美,不需要再生成它的子类,这时也应把它修饰为final类。 定义一个final类的格式如下:

final class ClassName{...}

**注意:**声明为final的类隐含地声明了该类的所有方法为final方法。

下面的结论是成立的:声明一个类既为abst\fract,又为final是非法的,因为抽象类必须被子类继承来实现它的抽象方法。下面是一个final类的例子:

final class A{...}class B extends A{//错误!不能继承A...}

2.)final``修饰成员变量 变量被声明为final后,成为常值变量(即常量),一旦被通过某种方式初始化或赋值,即不能再被修改。通常staticfinal`一起使用来指定一个类常量。例如:

static final int SUNDAY=0;

final变量用大写字母和下划线来表示,这是一种编码规定。

3.)final``修饰成员方法 用final修饰的方法为最终方法,不能再被子类重写,可以被重载。 尽管方法重写是Java非常有力的特征,但有时却需要避免这种情况的发生。为了不允许一个方法被重写,在方法的声明中指定final属性即可。例如:

class A{final void method(){}}class B extends A{//定义A类的一个子类Bvoid method(){}//错误,method()不能被重写}

该例中,因为method()方法在A中被声明为final,所以不能在子类B中被重写。如果这样做,将导致编译错误。 方法被声明为final有时可以提高性能:编译器可以自由地内联调用它们,因为它“知道”它们不会被子类重写。

class A{…}class B extends A{//错误!不能继承A…}


`2.`)final``修饰成员变量 变量被声明为`final`后,成为常值变量(即常量),一旦被通过某种方式初始化或赋值,即不能再被修改。通常static`与`final`一起使用来指定一个类常量。例如:

static final int SUNDAY=0;


把`final`变量用大写字母和下划线来表示,这是一种编码规定。

`3.`)final``修饰成员方法 用`final`修饰的方法为最终方法,不能再被子类重写,可以被重载。 尽管方法重写是`Java`非常有力的特征,但有时却需要避免这种情况的发生。为了不允许一个方法被重写,在方法的声明中指定`final`属性即可。例如:

class A{final void method(){}}class B extends A{//定义A类的一个子类Bvoid method(){}//错误,method()不能被重写}


该例中,因为`method()`方法在`A`中被声明为`final`,所以不能在子类`B`中被重写。如果这样做,将导致编译错误。 方法被声明为`final`有时可以提高性能:编译器可以自由地内联调用它们,因为它“知道”它们不会被子类重写。

标签:Java,重写,void,接口,public,抽象类,方法,final
From: https://blog.csdn.net/weixin_73749601/article/details/144521632

相关文章

  • Java项目整合Redis
    业务分析(思路)一个正常的业务操作是从前端到后端再到数据库,以商城的商品详情为例,当用户点击一个商品跳转进入详情页面时,从前端传入此商品的id,通过请求发至后端,后端接收该参数后即执行相应的方法,执行数据库sql操作。那么假定一个商城有十万或者数十万甚至更多的商品,那么商品数......
  • Java基础知识
    Java基础01.注释注释不会被执行!书写注释是一个非常好的习惯!!!平时写代码一定要注意规范!!Java中的注释有三种:单行注释多行注释文档注释具体操作代码如下:publicclassHelloWorld{publicstaticvoidmain(String[]args){//单行注释:只能注释一行文字......
  • Java如何用HaspMap统计次数并排序详解
    java统计单词频率继上一讲Java用PDFTextStripper来解析pdf文件提取文字-ivanlee717-博客园讲了如何接收和解析pdf之后,我们把pdf文件全部转为了String类型的字符串,那么这一讲聊聊怎么去统计每个词出现的频率。正则过滤首先我们需要把单词弄出来,把其他的文字过滤掉。Pattern......
  • JAVA健身房管理系统设计与实现
    大家好我是小俊学长,混迹在java圈的辛苦码农。今天要和大家聊的是一款《JAVA健身房管理系统设计与实现》毕业设计项目。项目源码以及部署相关请联系小俊学长,文末附上联系信息。......
  • (2024最新毕设合集)基于SpringBoot的社交型音乐网站+25664|可做计算机毕业设计JAVA、PHP
    目 录摘要1绪论1.1研究背景与意义1.3研究内容1.4论文结构与章节安排2 社交型音乐网站分析2.1可行性分析2.2系统流程分析2.2.1数据增加流程2.2.2数据修改流程2.2.3数据删除流程2.3 系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4 ......
  • 生鲜供应系统|Java|SSM|VUE| 前后端分离
                 【技术栈】1⃣️:架构:B/S、MVC2⃣️:系统环境:Windowsh/Mac3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7+4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html5⃣️数据库可视化工具:navicat6⃣️服务器:SpringBoot自带apachetomcat......
  • java小知识-ShutdownHook(优雅关闭)
    作者:京东物流崔冬冬一、先提出一个问题我们如果在JVM退出的时候做一些事情,比如关闭远程链接,怎么实现呢?二、ShutdownHook简介java里有个方法Runtime.getRuntime#addShutdownHook,是否了解呢?ShutdownHook是什么意思呢,看单词解释“关闭钩子”,addShutdownHook就是添加一个关闭钩......
  • 浅谈Java内省
    作者:京东物流王国泰一、什么是内省讲内省,不得不说JavaBean,Bean在Java中是一种特殊的类,主要用于装载数据,数据会被存储在类的私有属性中,通常具有无参构造函数、可序列化、以及通过getter和setter方法来访问属性。内省是JavaBeans规范的一部分,使用java.beans包中的类来实现,最常......
  • 5年Java到AI大模型,一名程序员的转型之旅,自学成功上岸!!
    在这个科技飞速发展的时代,技术的更新换代犹如潮水般汹涌。作为一名有着5年Java开发经验的程序员,我意识到自己需要适应这种变化,寻找新的职业增长点。随着人工智能(AI)和机器学习领域的迅猛发展,以及AI大模型在各个行业应用的不断扩展,我看到了这个领域蕴藏的巨大潜力和机会。因此......
  • 【毕业设计】A074-基于Java的电影院购票系统设计与实现
    ......