首页 > 其他分享 >面向对象基础

面向对象基础

时间:2023-08-29 20:45:53浏览次数:36  
标签:子类 void 基础 接口 public 面向对象 方法 class

面相对象

基础

定义

类是共同特征的描述、对象是真实存在的具体实例

用来描述一类事物的类叫javabean类,javabean类中不写main方法,编写main方法的类叫测试类,可以在测试类中创建javabean类的对象并赋值调用

一个java文件中可以定义多个class类,而且只能有一个是public修饰,public修饰的类名必须成为代码文件名;事迹开发中开始建议一个文件定义一个class类

public class 类名{
	成员变量:修饰符 数据类型 变量名称 = 初始化值;一般不指定,存在默认值
	成员方法
	构造器
	代码块
	内部类
}
数据类型 细明 默认值
基本类型 byte short int lang 0
基本类型 float double 0.0
基本类型 boolean false
引用类型 类,接口,数组,String null
引出案例
public class phone {
    
    String brand;
    double price;

    public void call(){
        System.out.println("手机在打电话");
    }
    public void playGame(){
        System.out.println("手机在玩游戏");
    }

}
public class phoneT {
    public static void main(String[] args) {
        phone p = new phone();
        p.brand = "小米";
        p.price = 1999;
        System.out.println(p.price);   //1999.0
        p.call();   //手机在打电话
    }
}
public class girlFriend {

    String name;
    private int age;//针对每一个私有化的成员变量提供get(对外提供成员变量的值)和set(给成员变量赋值)方法
    private String gender;


    public void setAge(int age) {
        if (age > 18 & age < 25) {
            this.age = age;
        } else {
            System.out.println("非法参数");
        }
    }
    public int getAge() {
        return age;
    }

    public void setGender(String gender) {  //方法里的是局部变量,类里的是成员变量,同名变量可用
        this.gender = gender;  //没有this的话就是就近原则
    }
    public String getGender() {
        return gender;
    }


    public void eat() {
        System.out.println("在吃东西");
    }
    public void sleep() {
        System.out.println("在睡觉");
    }

    //如果我们没有写任何构造方法,虚拟机会给我们自动加一个空参构造方法
    public girlFriend(){
        System.out.println("空参构造方法");
    }

    //有参构造
    public girlFriend(String name,int age){
        this.name = name;
        this.age = age;

    }
}
public class grilFrientT {
    public static void main(String[] args) {
		
        girlFriend g1 = new girlFriend();       		 //空参构造方法
        g1.name = "小老虎";
        g1.setAge(22);
        System.out.println(g1.getAge());        		  //22
        g1.eat();                                         //在吃东西
        
	 	//调用的空参构造
        girlFriend g2 = new girlFriend();              //空参构造方法

        girlFriend g3 = new girlFriend("小狮子",18);      
        System.out.println(g3.getAge());                  //18
        System.out.println(g3.name);                      //小狮子
    }

}
标准javabean类

用来描述一类事物的类

类名见名知意,成员变量用private修饰,提供至少两个构造方法空参全参,成员方法提供每一个成员变量的getset方法

快捷键

alt + insert
alt + fn + insert
构造方法

也叫构造器,构造函数,在创建对象的时候给成员变量进行初始化的

public class Student{
	修饰符 类名(参数){
		方法体;
	}
	public Student(){
		//空参构造方法,初始化对象时成员变量的数据均采用默认值
	}
	public Student(String name,int age){
		//带全部参数构造方法
		this.name = name
		//测试类就能直接赋值new Student("zs",12)
	}
}

方法名与类名相同,没有返回值类型,void也没有,没有具体的返回值,不能写return;

创建对象的时候由虚拟机调用,不能手动调用构造方法,每创建一次对象,就会调用一次构造方法;

如果没有定义构造方法,系统会给出一个默认的无参构造方法,定义了构造方法,系统不再提供默认的构造方法;

构造方法的重载:

带参构造方法和无参构造方法两者方法名相同,但是参数不同,叫构造方法的重载

无论是否使用都要写上无参和带全部参数的构造方法

构造方法是创建对象的时候,虚拟机会自动调用构造方法,给成员变量进行初始化

成员变量和局部变量
区别 成员变量 局部变量
类中位置不同 类中,方法外 方法内,方法申明上
初始化值不同 有默认的初始化值 使用之前要赋值
内存位置不同 堆内存 栈内存
生命周期不同 随对象创建而存在,随对象消失而消失 随着方法的调用存在,方法运行结束后消失
作用域 整个类中有效 当前方法中有效

就是文件夹,用来管理各种不同功能的java类

命名规则:公司域名反写+包的作用,全英文,见名知意:com.ithaime.domain

package com.ithaime.domain
public class Student{私有化成员变量,构造方法,成员方法}

使用其他类时需要用全类名(包名+类名)

public class Test{
	psvm{
		com.ithaime.domain.Student s = new com.ithaime.domain.Student();
	}
}

导包:

import com.ithaime.domain.Student;
public class Test{
	psvm{
		tudent s = new Student();
	}
}

使用同一个包中的类时不需要导包,使用java.lang中的类时不需要导包,其他情况需要导包;如果同时使用两个包中的同名类,需要用全类名

权限

权限修饰符

作用范围由小到大:private<缺省/默认<protected<public

权限修饰符 同一个类中 同一个包中其他类 不同包下的子类 不同包下的无关类
private 1
空着不写 1 1
protected 1 1 1
public 1 1 1 1

一般都是成员变量私有,方法公开;如果方法中的代码是抽取其他方法中的共性代码,这个方法一般也私有

抽象类和抽象方法

作用:

  • 抽取共性时,无法确定方法体,就把方法定义为抽象的强制让子类按照某种格式重写

子类没有重写的话没办法,那就别写方法体了,用一个抽象关键字修饰

抽象方法子类必须强制重写,并按父类的格式(统一)

如果一个类中存在抽象方法,该类就必须声明为抽象类

public abstract class 类名{
	public abstract 返回值类型 方法名(参数);
}

特点:

  • 抽象类不能实例化

  • 抽象类不一定有抽象方法,有抽象方法一定是抽象类

  • 可以有构造方法;创建子类对象时给属性赋值

    • 抽象类是父类的话就要把子类中的共同方法抽取上来,创建子类对象时给共有属性赋值
  • 抽象类的子类要么重写抽象类中的所有抽象方法,要么子类本身是抽象类

    • 但是子类也是抽象类的话也不能创建实例对象,要创建对象还要写一个孙子类再继承子类重写所有抽象方法

示例:

public abstract void work();

子类继承后重新里面的所有抽象方法

public void work(){
    System.out.print("学习")
}

没有方法体的方法

抽象类不能创建对象

设计的时候先正常写,当有抽象方法时再把父类变成抽象类

  • 意义

算是一个标准,其他人实现方法要统一【强制子类按照父类的格式进行重写】

static

静态变量是所有对象共享的

修饰成员变量(静态变量):被该类所有对象共享,不属于对象;属于类;静态变量是随类的加载而加载的,优于对象出现

类名调用(每个类都有),对象名调用

修饰成员方法(静态方法):多用在测试类和工具类中,javabean中很少用到,类名调用,对象名调用

有一个专门的静态存储位置(静态区),在堆内存里,每一个new出来的都和静态区的内容连起来

例子:

新增一个公共类:共同的老师
public String teacherName
给对象赋值:
s1.teacherName = "zs"  // zs
s2没操作 // null

public Static String teacherName
s1.teacherName = "zs"  // zs
s2没操作 // zs
也能直接调用
Student.teacherName = "zs" //s1和s2都能获得
  • Static的注意事项
    • 静态方法只能访问静态变量和静态方法
    • 非静态变量可以访问静态变量或静态方法,也可以访问非静态的成员变量和非静态的成员方法
    • 静态方法没有this关键字

非静态成员方法的形参中有一个隐藏的this,调用方法的时候虚拟机赋值的,表示当前方法调用者的地址值

调用非静态的成员方法时前面也有一个隐藏的this

静态方法不能调用非静态的成员变量,因为没有this关键字

静态方法不能调用实例变量

静态方法不能调用非静态的成员方法

  • main方法

    • public:被JVM调用,访问权限足够大
    • static:被JVM调用,不用创建对象,直接类名访问。因为main方法是静态的,所以测试类中其他方法也需要是静态的。
    • void:被JVM调用,不需要给JVM返回值
    • main:一个通用的名称,虽然不是关键字,但是被JVM识别
    • String[] args:以前用于接收键盘录入数据的,现在没用
  • 测试类

用来检查其他类是否正确,带有main方法的类,是程序的入口

  • 工具类--静态方法的使用

不是用来描述一类事物的,用来帮助我们做一些事情的类

类名见名知意,私有化构造方法(为了不让外界创建),方法定义为静态(方便调用)

public class ArrUtil{
	private ArrUtil(){} //私有化构造方法
	
	public static int getMax(){...}
	public static int getMin(){...}
	public static int getSum(){...}
	public static int getAvg(){...}
}

例子:

public class ArrayUtil(){
    private ArrayUtil(){}
    public static double getAverage(double[] arr){
        double sum = 0;
        for (int i = o; i < arr.length;i++){
            sum = sum+arr[i]
        }
        return sum/arr.lengrh;
    }
}

main:
double[] arr = {1.1,2.2};
double avg = ArrayUtil.getAverage(arr);
sout:avg

关键字

private关键字

权限修饰符,可以修饰成员(成员变量,成员方法),被private修饰的成员只能在本类中才能访问

用public修饰getset方法

就近原则和this关键字
public class G{
	private int age;
	public void method(){
		int age = 10
		sout:age   //10就近原则
		sout:this.age // 0,直接在成员位置找
		this.age = age // 把测试类中调用方法传递过来的age给成员位置的age
	}
}

this的内存原理:

this区分局部变量和成员变量

this本质是所在方法调用者的地址值

new出来的都在堆内存里,方法依次进栈

对象内存图

从JDK8开始,取消方法区,新增元空间.
把原来方法区的多种功能进行拆分
有的功能放到了堆中,有的功能放到了元空间中。

  • 一个对象

    • 加载class文件
    • 申明局部变量
    • 在堆内存中开辟一个空间
    • 默认初始化
    • 显示初始化
    • 构造方法初始化
    • 将堆内存中的地址值赋值给左边的局部变量

    对堆空间的对象来讲,没有变量指向这个空间,这个空间就会消失变成垃圾

Final关键字

修饰方法:不能被重写,最终方法,父类写show()后子类不能重写

public final void show(){}

修饰类:最终类,不能被继承

final class Fu{}

修饰变量:常量,只能被赋值一次

final int a = 1;

常量:一般作为系统的配置信息,方便维护,提高可读性,单个单词全部大写,多个单词全部大写用下划线隔开;

final修饰的变量是基本类型,变量存储的数据值不能发生改变。

final修饰的是引用类型,地址值不可变,对象内部的可以改变;属性值等

字符串是不可变的:

private final
继承关键字super

this就是一个局部变量,方法被调用的时候就有值

super代表父类存储空间

//需求:默认为ch
public stu(){
    //调用本类其他构造方法,虚拟机就不会再添加super()
    this(null.0."ch")
}
public stu(String name,int age,String school){
    super();
    this.name = name;
    this.age = age;
    this.school = school;
}
继承关键字extends

子类重复的代码抽取到父类(基类或超类)中,提高代码复用性,子类(派生类)还可以增加其他功能,使子类更强大

类与类之间存在相同的内容,并且满足子类是父类的一种,就可以考虑使用继承

public class Student extends Person{}  //Student是子类,Person是父类

封装

对象代表什么,就得封装对应的数据,并提供数据对应的行为。

继承

  • 特点

java只支持单继承(一个子类只能继承一个父类),不支持多继承(子类不能同时继承多个父类),但支持多层继承

每个类都直接或间接继承Object

public class A {}  ==> public class A extends Object  //虚拟机加的

子类只能访问父类中非私有的成员

  • 子类能继承父类中哪些内容
构造方法 public 不能 private 不能
成员变量 public 能 private 能
成员方法 public 能 private 不能

成员变量可以被继承下来,但是不能调用

构造方法:public修饰的类要跟文件名保持一致

成员变量的访问特点

就近原则,现在局部位置找,本类成员位置找,父类成员位置找,逐级往上

出现重名变量:

sout:name
sout:this.name
sout:super.name
继承中成员方法的访问特点

虚方法表:非private,非static,非final

虚方法才能被继承

继承是在父类基础上添加自己类中的虚方法

方法重写

继承体系中,子类出现了和父类中一模一样的方法声明,就称子类的这个方法时重写的方法@Override

子类覆盖了从父类中继承的虚方法表中的方法

方法重写的本质是覆盖虚方法表中的方法

方法重写:

  • 重写方法的名称,形参列表必须与父类中的一致
  • 子类重写父类方法时,访问权限子类必须大于等于父类【缺省<protected<public】
  • 子类重写父类方法时,返回值类型子类必须小于等于父类
  • 私有方法不能被重写
  • 子类不能重写父类的静态方法
  • 只有被添加到虚方法表中的方法才能被重写
  • 重写的方法尽量与父类保持一致
构造方法的访问特点

有一个虚拟机自动默认添加的无参构造

  • 父类的构造方法不会被子类继承
  • 子类的所有构造方法默认先访问父类中的无参构造,再执行自己

子类默认有一个隐藏的super()方法在最上面调用父类的无参构造

  • 子类不能继承父类的构造方法,但是可以通过super调用
  • 子类构造方法的第一行有一个默认的super();
  • 默认先访问父类中无参构造,再执行自己
  • 想要有参的父类构造,必须手动写

多态

概述

多态是同类型的对象表现出的不同形态【对象的多种形态】

方法的参数是一个类,此时就可以传递这个类所有的子类对象

  • 前提:

有继承/实现关系

有父类引用指向子类对象

有方法重写

  • 好处:

使用父类作为参数可以接收所有子类对象,有扩展性

父类类型 对象名称 = 子类对象;

学生形态 对象
Student s = new Student()
人的形态 对象
People p = new Student()
Fu f = new Zi();
//Teacher Student Administrator
public void register(Person p){
	p.show() // 根据传递对象的不同调用不同的show方法
}

例子:

People-Student、Teacher
Test
public class People {
    private String name;
    private int age;

    public People() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public void show(){
        System.out.println(name+","+age);
    }
}
public class Student extends People{
    public void show(){
        System.out.println("学生的信息"+getName()+","+getAge());
    }
}
public class Teacher extends People{
    public void show(){
        System.out.println("老师的信息"+getName()+","+getAge());
    }
}
public class Test {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("zs");
        s.setAge(18);

        Teacher t = new Teacher();
        t.setName("ww");
        t.setAge(39);

        register(s);
        register(t);

    }
    public static void register(People p){
        p.show();   //学生的信息zs,18;老师的信息ww,39
    }
}
多态中调用成员的特点

变量调用:编译看左边,运行也看左边

方法调用:编译看左边,运行看右边

堆内存有个方法区,test->animal->dog;new出来后堆内存一个地方有两个name,在子类的对象中,会把父类的成员变量也继承下去,子类中对方法进行了重写,在虚方法表汇总会把父类的方法覆盖

psvm{
	Animal a = new Dog();
	sout:a.name // animal
	a.show();   // Dog
}
class Animal{name,show()}
class Dog extends Animal{anme,show()}
  • 调用成员变量: 编译看左边,运行也看左边

    • 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。

    • 运行也看左边: java运行代码的时候,实际获取的就是左边父类中成员变量的值

  • 调用成员方法: 编译看左边,运行看右边

    • 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。
    • 运行看右边: java运行代码的时候,实际上运行的是子类中的方法。
public class Animal {
    String name = "动物";
    public void show(){
        System.out.println("animal");
    }
}
class Dog extends Animal{
    String name = "狗";
    @Override
    public void show(){
        System.out.println("dog");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal a = new Dog();
        System.out.println(a.name);//动物
        a.show(); // dog
    }
}
多态的优势和弊端
  • 优势

    • 在多态形式下,右边的对象可以实现解耦合,便于扩展和维护
    Person p = new Student();
    p.work; // 业务逻辑发生改变,后续代码无需修复,比如换成老师工作,work里的方法会自动变
    
    • 定义方法时,使用父类作为参数,可以接收所有子类对象,体现多态的扩展性与遍历
  • 弊端:不能调用子类的特有方法

    • 调用成员方法编译看左边运行看右边
  • 引用数据类型转换

    • 方式1:自动类型转换Person p = new Student()
    • 方式2:强制类型转换Student s = (Student)p
      • 作用
      • 可以转换成真正的子类类型,从而调用子类独有功能
      • 转换类型与真实对象类型不一致会报错
      • 转换的时候用instanceof关键字进行判断
  • 弊端解决:调用者变成子类类型就可以

Dog d = (Dog) a // Animal
d.lockHome();
  • 判断要转换的类型
if(a instanceof Dog){
    Dog d = (Dog) a;
	d.lookHome();
}else if(a instanceof Cat){
    Cat c = (Cat) a;
    c.catchMouse();
}else{
    ...
}

jdk14新特性:先判断是否为dog类型,是则强转,并赋变量名d,不是不强转,结果false

if(a instanceof Dog d){
	d.lookHome();
}else if(a instanceof Cat c){
    c.catchMouse();
}else{
    ...
}

代码块

  • 局部代码块:方法里面;用完之后立马回收;执行完a就从内存里消失;

提前结束变量的声明周期,a只能在局部代码块里才能使用

节约内存

psvm{
	{
		int a = 1;
		sout:a   // 1
	}   //a从内存消失
	sout:a  // 无
}
  • 构造代码块:写在成员位置的代码块;

优先于构造方法执行,创建本类对象时会先执行构造代码块再执行构造方法;

优先于构造方法,把多个构造方法中的重复的代码写在构造代码块【不够灵活】,有的不想用也没办法;

public class Student{
	private String name;
	private int age;
	{
		sout:开始创建对象了
	}
	public Student(){
        //sout:开始创建对象了
    }
	public Student(String name,int age){
        //sout:开始创建对象了;
        this.name = name;
        this.age = age;
    }
}

多个构造方法有重复可以:把重复代码写在一个中,其他的构造方法里迪this调用本类其他构造

public class Student{
	private String name;
	private int age;
	
	public Student(){
        this(null,0);
    }
	public Student( String name,int age){
        sout:开始创建对象了;
        this.name = name;
        this.age = age;
    }
}

重复代码抽取成一个方法

public class Student{
	private String name;
	private int age;
	
	public Student(){
	方法()
	}
	public Student(String name,int age){
	方法();
	this.name = name;
	this.age = age;
	}
}
  • 静态代码块:static{}

随着类的加载而加载,自动触发,只执行一次;在类加载的时候,做一些数据初始化的时候用

可以进行数据初始化,数据比较安全,可以在登录前先初始化一些用户信息

接口

不是所有子类都有某个行为

animal- -> 兔子(不会游泳),青蛙(会)、狗(会)
定义一个游泳的接口

就是一种规则,是对行为的抽象

public interface 接口名{}

接口不能实例化

接口和类之间是实现关系,通过implements关键字表示,可以多实现

public class 类名 implements 接口名{}

接口的子类称为实现类,要么重写接口中的所有抽象方法,要么实现类本身是抽象类

public class 类名 implements 接口名1,接口名2{}
public class 类名 extends 父类 implements 接口名1,接口名2{}

例子:

public interface Swim{
	public abstract void swim();
}

抽象类更多的用在父类中,抽取共性方法的时候,方法体不一样就可以写成抽象方法,抽象方法所在的类就是抽象类

比如动物抽象类,接口是行为,比如游泳行为

接口中成员的特点

成员变量只能是常量

默认修饰符public static final

没有构造方法

成员方法只能是抽象方法,默认修饰符public abstract【方法会默认自动加上public abstract】

jdk7以前接口中只能定义抽象方法

jdk8接口中可以定义有方法体的方法

jdk9接口中可以定义私有方法

接口与类之间的关系

多个接口中有重名方法,只需要重写一次

  • 类和类的关系
    • 继承关系,只能单继承,不能多继承,但是可以多层继承
  • 类和接口的关系
    • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系
    • 继承关系,可以单继承,也可以多继承

实现类实现了最下面的子接口需要重写所有的抽象方法

接口中新增的方法
  • JDK7以前: 接口中只能定义抽象方法、
  • JDK8的新特性: 接口中可以定义有方法体的方法。(默认、静态)
  • JDK9的新特性: 接口中可以定义私有方法(普通的和静态的)

接口发生变化所有实现类就必须跟着改变,接口中的抽象方法不能拥有方法体;如果接口里面的方法可以有方法体就不用跟着修改了

public interface Inter{
	public abstract int method();
	//定义有方法体的方法
}

接口升级时:此时实现类就不需要立马修改了,等以后用到某个规则了,再重写就行了

public interface Inter{}
public class InterImplA implements Inter{}
public class InterImplB implements Inter{}
。。。
加入10个新方法
    

JDK8以后接口中新增的方法:

  • 接口中默认方法

    • 允许在接口中定义默认方法需要使用关键字default 修饰
      • 作用: 解决接口升级的问题
    • 接口中默认方法的定义格式:
      • 格式:public default 返回值类型 方法名(参数列表){}
      • 范例: public default void show(){}
    • 接口中默认方法的注意事项
      • 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字
      • public可以省略,default不能省略
      • 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
  • 接口中静态方法

    • 允许在接口中定义定义静态方法,需要用static修饰
    • 接口中静态方法的定义格式
      • 格式:public static 返回值类型 方法名(参数列表){}
      • 范例: public static void show()[
    • 接口中静态方法的注意事项
      • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
      • public可以省略,static不能省略
public interface Inter {
    public abstract void method();
    public static void show() {
        System.out.println("接口中的静态方法");
    }
}
public class interImpl implements Inter{
    @Override
    public void method() {
        System.out.println("只要求重写抽象方法,静态方法不需要重写");
    }

    //不叫重写,只是一个重名方法o.0
    public static void show(){
        System.out.println("重写");
    }
}
public class Test {
    public static void main(String[] args) {
        Inter.show();
        interImpl.show();
        // 子类把从父类继承下来的虚方法里面的方法进行覆盖了才叫重写
        // 静态的,私有的,最终的不会添加到虚方法表
    }
}

jdk9以后添加的私有方法

interface Inter{
	public default void m1(){
        sout;
        log();
    }
    public default void m2(){
        sout;
        log();
    }
}

//public defult void log(){
//不想让别人用,没有意义,只是一些重复的代码
private void log(){ 
    sout:方法
}

接口中私有方法的定义格式

  • private 返回值类型 方法名(参数列表){}

    private void show(){}
    
  • private static 返回值类型 方法名(参数列表){}

     private static void method(){}
    
public interface InterA {
    public default void show1(){
        System.out.println("show1");
        show3();
    }
    public static void show2(){
        System.out.println("show2");
        show4();
    }
    //普通的私有方法,给默认方法服务的
    private void show3(){
        System.out.println("3");
    }
    
    //静态的私有方法,给静态方法服务的
    private static void show4(){
        System.out.println("4");
    }
}
接口的应用

编译看左边运行看右边

接口代表规则,是行为的抽象,想要让哪个类拥有一个行为,就让这个类实现对应的接口就行

当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称为接口多态

public interface 运输{}
public void 搬家(运输接口 c){}
接口类型 j = new 实现类对象();
搬家(车对象);
搬家(搬家公司);
适配器设计模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。设计模式就是各种套路

适配器设计模式:解决接口与接口实现类之间的矛盾问题

接口中方法太多,有十几个;实现的时候要重写所有的,但是现在只要第5个

适配器设计模式:在中间新建一个类,让中间这个类实现接口,空实现所有方法,新类就不用实现借口了,只需要继承中间的适配器Adapter,新类中需要用到哪个方法就重写哪个方法

适配器是空实现,一般写成抽象的,不让外界创建适配器对象

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

  • 编写中间类XXXAdapter,实现对应的接口
  • 对接口中的抽象方法进行空实现
  • 让真正的实现类继承中间类,并重写需要用的方法
  • 为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

实现类还要继承其他的类的话,让适配器继承其他类就行

内部类

类的五大成员:属性,方法,构造方法,代码块,内部类

在一个类里面再定义一个类

public class Outer{       // 外部类
	public class Inter{   // 内部类
		
	}
}
public class Test{psvm}   // 外部其他类

在外部其他类中创建内部类的对象并调用内部类的方法

  • 应用场景

b类表示的事物是a事物的一部分,且b单独存在没有意义,比如汽车的发动机,arrayList的迭代器,人的心脏等

public class car{
	String carName;
	int carAge;
	int carColor;
	public void show(){
		sout:this.carName;
		Engine e = new Engine();
		sout:e.engineName
	}
	class Engine{
		String engineName;
		int engineAge;
		public void show(){
			sout:carName;
			sout:engineName
		}
	}
}

内部类表示的事物是外部类的一部分,内部类单独出现没有意义;

内部类可以直接访问外部类的成员,包括私有;

外部类要访问内部类的成员必须创建对象;

成员内部类

写在成员位置的,属于外部类的成员

成员内部类可以被一些修饰符所修饰;如private,默认,protected,public,static

$区分内部类

public class car{    // 外部类
	String carName;
	int carAge;
	int carColor;
	
	class Engine{    // 成员内部类
		String engineName;
		int engineAge;
	}
}
  • 获取

    • 当成员内部类被private修饰时,在外部类编写方法,对外提供内部类对象

    • 当成员内部类被非私有修饰时,直接创建对象【外部类名.内部类名 对象名 = 外部类对象. 内部类对象;】

      Outer.Inner oi = new Outer().new Inner();
      
  • 外部类成员变量月内部类成员变量重名时,内部类访问

    Outer.this.变量名
    
  • private修饰的话

    • 用piblic

    • 外部类提供一个方法,方法中返回内部类的对象,在外部通过方法获取内部类的对象

package neibulei;

public class Outer {
    String name;
    public class Inner{
        
    }

    public Inner getInstance(){
        return new Inner();
    }
}
package neibulei;

public class Test {
    public static void main(String[] args) {
        
        Outer.Inner oi = new Outer().new Inner();
        
        Outer o = new Outer();
        System.out.println(o.getInstance());
        //neibulei.Outer$Inner@4eec7777
    }
}

在成员内部类里,jdk16之前不能定义静态变量

成员内部类如何获取外部类的变量

package neibulei;

public class Outer2 {
    private int a = 10;
    class Inner{
        private int a = 20;
        public void show(){
            int a = 30;
            System.out.println(a);
            System.out.println(this.a);
            //inner和outer不是继承关系,不能用super
            System.out.println(Outer2.this.a);
            //编译之后Outer和Inner是两个独立的文件
            //Outer2$Inner.class
        }
    }
}
package neibulei;

public class Test2 {
    public static void main(String[] args) {
        Outer2.Inner oi = new Outer2().new Inner();
        oi.show();
    }
}
静态内部类

静态内部类是一种特殊的成员内部类

只能访问外部类中的静态变量和静态方法

访问非静态的需要创建对象,根据对象访问变量和方法

public class Car{
    String carName;
    int carAge;
	static class Engine{
        String engineName;
        int engineAge;
    }
}
  • 静态内部类对象的方式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
  • 调用静态内部类中的方法:

    • 非静态方法: 先创建对象,用对象调用

    • 静态方法: 外部类名.内部类名.方法名()

package neibulei;

public class Outer {
    int a = 10;
    static int b = 20;
    static class Inner{
        public void show1(){
            System.out.println("非静态方法show1");
//            System.out.println(a);//报错
            Outer o = new Outer();
            System.out.println(o.a);
            System.out.println(b);
        }
        public static void show2(){
            System.out.println("静态方法show2");
//            System.out.println(a);//报错
            Outer o = new Outer();
            System.out.println(o.a);
            System.out.println(b);
        }
    }
}
package neibulei;

public class Test {
    public static void main(String[] args) {
        //静态的都可以类名.获取
        Outer.Inner oi = new Outer.Inner();
        oi.show1();
        oi.show2();
        Outer.Inner.show2();
    }

}
局部内部类

将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量

外界是无法直接使用,需要在方法内部创建对象并使用。

该类可以直接访问外部类的成员,也可以访问方法内的局部变量

package neibulei;

public class Outer4 {
    public void show(){
        int a = 10;

        int b = 20;

        //局部内部类
        class Inner{
            String name;
            int age;

            public void p(){
                System.out.println(a);
                System.out.println(b);
            }
            public void method1(){
                System.out.println("局部内部类里的1方法");
            }
            public static void method2(){
                System.out.println("局部内部类里的静态2方法");
            }
        }

        //创建局部内部类的对象
        Inner i = new Inner();
        System.out.println(i.name);
        System.out.println(i.age);

        i.method1();
        Inner.method2();
    }

package neibulei;

public class Test4 {
    public static void main(String[] args) {
        Outer4 o = new Outer4();
        //无法直接调用show方法里的a
//        o.a;
        o.show();
        //null
        //0
        //局部内部类里的1方法
        //局部内部类里的静态2方法
    }
}
匿名内部类

隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置

  • 匿名内部类的格式

    new 类名或者接口名(){
        重写方法;
    };
    
  • 格式的细节

    • 包含了继承或实现,方法重写,创建对象
    • 整体就是一个类的子类对象或者接口的实现类对象
  • 使用场景

    • 当方法的参数是接口或者类时;以接口为例,可以传递这个接口的实现类对象;如果实现类只要使用一次,就可以用匿名内部类简化代码

把前面的class删掉,剩余的内容就变成了一个没有名字的类

这个没有名字的类想要实现Swim接口把Swim写在了大括号的前面,表示这个没有名字的类实现了Swim接口,所以需要在类中重写接口里面所有的抽象方法

还想要创建这个没有名字的类的对象,new

对应实现(继承)关系,方法的重写,创建对象

new的不是swim接口,而是后面的类

名字只是不需要自己起,是外部类$序号.class

public class Student implements Swim{
    @Override
    public void swim(){
        System.out.println("重写")
    }
}

public interface Swim{
    public abstract void swim();
}

new Swim(){
    @Override
    public void swim(){
        System.out.println("重写")
    }
}

应用

测试类调用method方法

zi extends Animal{
	Dog d = new Dog();
	method(d)
}

如果dog类只用一次,单独定义一个子类太麻烦

method(
	new Animal(){
		@Override
		public void eat(){
			 System.out.println("重写方法")
		}
	}

);
public static void method(Animal a){  //Animal a= 子类对象,多态
    a.eat();  //编译看左边,
}

接口多态,swim接口的实现对象

Swim s = new Swim(){
    @Override
    public void swim(){
        System.out.println("重写方法")
    }
};
s.swim();

整体是个对象,后面的{}才是类

new Swim(){
    @Override
    public void swim(){
        System.out.println("重写方法")
    }
}.swim();
//对象可以调用自己的方法

标签:子类,void,基础,接口,public,面向对象,方法,class
From: https://www.cnblogs.com/lmcool/p/oop.html

相关文章

  • 提示学习方法-AI基础系列文章第15篇
            使用生成式AI解决问题的学习提示法是一个在生成式AI领域解决问题的框架。它可以帮助你决定生成式AI是否是正确的解决方案,如何应用提示工程,选择什么工具等等。我们将逐一介绍这五个步骤,然后提供一个使用这种方法的案例研究。五个步骤陈述你的问题学习提示法的第一步......
  • Ftp基础(一):基于Vsftpd(主动模式和被动模式)安装Ftp
      如果是Windows下,我们一般使用IIS来部署一套Ftp,如果是Linux下,个人一般使用Vsftpd来搭建一套Ftp。  至于什么是Ftp,就不介绍了,本文就Ubuntu下安装配置Vsftpd,CentOS其实差不多,所以这里就当做笔记了  安装    Ubuntu下安装Vsftpd很简单,使用apt安装即可  #更新......
  • 数据库备份和Shell基础测试及AWK(运维)
    第一题:使用MySQL命令进行备份和恢复的步骤如下:备份test库:使用mysqldump命令备份test库,并将备份写入一个.sql文件中。命令示例:mysqldump-u用户名-p密码test>backup.sql恢复备份:使用mysql命令将备份文件中的数据恢复到test库中。命令示例:mysql-u用户名-p密码test<backu......
  • java基础(根据狂神总结)
    java基础(狂神)注释单行//多行/**/文档注释(可以加参数)/****/***@Descriptionhelloworld*@Authorcheems*/}数据类型类型基本数据类型数值类整数(查看最大字节大小,通过对应的类的源码看)byte占1个字节short2in......
  • js面向对象浅析-表单生成
    js面向对象浅析-表单生成前言:这里就表单生成器的案例对js面向对象分析一下。。。(function(window){varFormBuilder=function(data){this.data=data;};window.FormBuilder=FormBuilder;})(window);FormBuilder.prototype.create=function(){va......
  • B端基础规范
    B端基础规范框架层:内容层(主要内容区域)|基础层(导航区域)|叠层(弹窗提示悬浮);框架:基础层——上下布局、“T”型布局、“口”型布局;常见布局01、传统布局方式:考虑分辨率的兼容问题;02、弹性布局方式:比较适合表单和表格多的产品;不会改变:文字大小、图标大小、固定高度的......
  • day①-python基础
    Python介绍发展史Python2or3?安装HelloWorld程序变量用户输入模块初识.pyc是个什么鬼?数据类型初识数据运算表达式if...else语句表达式for循环breakandcontinue 表达式while循环作业需求 一、Python介绍python的创始人为吉多·范罗苏姆(GuidovanR......
  • [java基础知识复习] Java基础知识总结分享一
    写代码:1,明确需求。我要做什么?2,分析思路。我要怎么做?1,2,3。3,确定步骤。每一个思路部分用到哪些语句,方法,和对象。4,代码实现。用具体的java语言代码把思路体现出来。学习新技术的四点:1,该技术是什么?2,该技术有什么特点(使用注意):3,该技术怎么使用。demo4,该技术什么时候用?test。————......
  • 面向对象(构造、析构、拷贝、赋值、友元)
    文章目录一、面向对象的基本概念1、面试题--->面向对象的基本原则?2、面试题--->空类会创造哪些成员函数?二、类和结构体1、面试题--->类和结构体的区别?三、成员变量及其初始化四、构造函数和析构函数1、构造函数和析构函数的调用顺序2、面试题--->析构函数为什么要定义为虚函数?3、......
  • JAVA SE基础《十》 ---- 面对对象高级一
    目录一、static  1、static修饰成员变量2、static修饰成员变量的应用场景:在线人数统计3、static修饰成员方法4、static修饰成员方法的应用场景:工具类5、static的注意事项6、static的应用知识:代码块7、static的应用知识:单例设计模式二、面向......