java类-内部类-抽象类-抽象方法-接口-接口组成更新-基本类型包装类-Integer类

概述

定义:
是对现实生活中一类具有相同属性和行为的事物的抽象。

特点:
①类是对象的数据类型
②类是具有相同属性和行为的一组对象的集合
③一个类可以对应多个对象,只要对象的属性和行为是相同的

类基础内容

类的重要性
是java程序的基本组成单位;


是对现实生活中一类具有相同属性和行为的事物的抽象,确定对象将拥有的属性和行为。

类的组成
属性和行为。
属性:在类中通过成员变量来体现(类中方法外的变量)
行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键词即可)

类相关内容
所有类的基类:java.lang.Object类。
main()函数的合法参数:String args[] 。

类的定义步骤

定义步骤:
①定义类
②编写类的成员变量
③编写类的成员方法

//①定义类
public class 类名(){
	//②编写类的成员变量
	变量1数据类型 变量1;
	变量2数据类型 变量2//③编写类的成员方法,定义方法去掉static关键字
	方法1;
	方法2}

案例:

// 说明:
类手机;
成员变量品牌、价格;
成员方法打电话、发短信;
// Demo110
public class Demo110 {
    //编写类的成员变量
    String brand;
    int price;
    
    //成员方法
    public void call(){
        System.out.println("打电话");
    }
    public void sendMessage(){
        System.out.println("发短信");
    }
}

标准类制作

制作要求:

  • 成员变量
    使用private修饰
  • 构造方法
    提供一个无参构造方法
    提供一个带多个参数的构造方法
  • 成员方法
    提供每一个成员变量对应的setXxx()/getXxx()
    提供一个显示对象信息的show()
  • 创建对象并为其成员变量赋值的两种方式
    无参构造方法创建对象后使用setXxx()赋值 ——》无参数构造方法 + setXxx()方法
    使用带参数构造方法直接创建带有属性值的对象 ——》有参数构造方法
    案例
// 111
//标准类制作
public class Student1 {
    //定义private修饰的成员变量
    private String name;
    private int age;
    //定义无参数和有参数的构造方法
    public Student1(){

    }
    public Student1(String name,int age){
        this.name = name;//this.name 表示的是类的成员变量 name表示的是局部变量
        this.age = age;
    }

    //提供给每一个成员变量对应的get/set方法
    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 StudentDemo1 {
    public static void main(String[] args){
        //使用无参数构造方法创建对象,使用setXxx()方法实现对成员变量的赋值
        Student1 stu1 = new Student1();
        stu1.setName("汪苏泷");
        stu1.setAge(33);
        stu1.show();//汪苏泷,33

        //使用带参数的构造方法创建对象并通过参数赋值
        Student1 stu2 = new Student1("许嵩",36);
        stu2.show();//许嵩,36
    }
}

内部类

概述

概念:
就是在一个类中定义一个类。

格式:

public class 类名{
	修饰符 class 类名{
	}
}
内部类修饰符 一般是private

特点:
①内部类可以直接访问外部类的成员,包括私有

public class Outer {
    //内部类可以访问外部类的成员
    private int age = 20;
    //内部类 Inter
    public class Inter{
        public void show(){
            System.out.println(age);
        }
    }
}

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

// 外部类 Outer
public class Outer {
    //内部类可以访问外部类的成员
    private int age = 20;
    //内部类 Inter
    public class Inter{
        public void show(){
            System.out.println(age);
        }
    }

    public void method(){
        //外部类访问内部类的成员,必须创建内部类的方法
//        show();//直接访问会报错
        Inter i = new Inter();
        i.show();
    }
}

内部类分类:
根据内部类在类中定义的位置不同:
①在类的成员位置:成员内部类
②在类的局部位置:局部内部类

成员内部类

格式
public class Outer {
    private int num = 20;
    //Inter就是Outer类的成员内部类
    public class Inter{
        public void show(){
            System.out.println(num);
        }
    }
}
访问
  • 内部类修饰符public
    成员内部类,外界创建对象访问
格式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
例子:Outer.Inter oi = new Outer().new Inter();

理解xhj:
出现内部类的原因是:把内部类的内容隐藏起来,不想让外界直接看到/访问。
则一般内部类定义 修饰符的位置private而不是public。

  • 内部类修饰符private
    内部类修饰符是private时,访问内部类的方法。
在外部类中 创建成员方法:创建内部类对象,通过对象调用方法实现访问;
在测试类中 创建外部类的对象,通过对象调用外部类成员方法的形式实现对内部类方法的访问。
public class Outer {
    private int num = 20;
    //Inter就是Outer类的成员内部类
	
	// 成员内部类 public修饰
	public class Inter{
        public void show(){
            System.out.println(num);
        }
    }
	// 成员内部类 private修饰
    private class Inter{
        public void show(){
            System.out.println(num);
        }
    }
    // 成员方法
    public void method(){
        Inter i = new Inter();
        i.show();
    }
}

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

		//内部类 采用修饰符public,可以采用下面方式访问内部类中的方法
        //成员内部类 public修饰 访问类的方法
/*        Outer.Inter oi = new Outer().new Inter();
        oi.show();*/
        

        //内部类 采用修饰符private,采用下述形式访问内部类方法。
        // 在外部类中写成员方法,方法中 创建内部类对象,通过对象.方法实现对内部类的访问。
        Outer o = new Outer();
        o.method();//20
    }
}

局部内部类

格式

位置是:在外部类成员方法中。

public class Outer {
    private int num = 10;
    
    public  void method(){
        class Inter{
            public void show(){
                System.out.println(num);
            }
        }
    }
}
访问

特点①
局部内部类是在方法中定义的类,所以外部是无法直接使用,需要在方法内部创建对象并使用。
特点②
该类可以直接访问外部类的成员变量,也可以访问方法内的局部变量。

public class Outer {
	//外部类的成员变量
    private int num = 10;
    public  void method(){
        //外部类成员方法内的局部变量
        int num2 = 30;
        class Inter{
            public void show(){
                System.out.println(num);//10
                System.out.println(num2);//20
            }
        }
        Inter i = new Inter();
        i.show();
        //创建外部类成员,不在内部类中创建对象、调用show方法,外部类创建的对象将不能访问局部内部类的show方法
    }
}
public class OuterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

分析

外部类的成员方法method
①method方法中只有局部内部类 Inter 
则对象.method→什么也不执行。

②method方法中有局部内部类InterInter类的实例化对象;对象.show方法,输出外部类的成员变量;
外部类对象.method→结果是外部类的成员变量num = 10

③method方法中有局部内部内InterInter类的实例化对象;对象.show方法,输出外部类的成员变量、method方法的局部变量;
对象.method→结果是外部类的成员变量num = 10、外部类成员方法的局部变量 num2 = 30

匿名内部类

概述

匿名内部类 = 是局部内部类的一种。

前提: 存在一个类或者接口,类可以是具体类或抽象类
格式:

new 类名或者接口名(){
	重写方法;
};

理解:
①new 类名或者接口名() ;
说明整体是一个对象,只不过对象没有名字,也称为匿名对象,即匿名类本质是一个匿名对象。
②重写方法,
说明它继承了前面的类 或者 实现了前面的接口。

本质:
是一个继承了该类或者实现了该接口的子类匿名对象。

案例 接口实现类的匿名内部类
// 接口
public interface Inter {
    //接口 = 抽象内容
    // 抽象方法
    public abstract void show();
}
//测试类
public class OuterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
public class Outer {
    //匿名内部类是局部内部类的一种,所以需要在外部类的方法中书写
    public void method(){
        //匿名内部类的前提是 存在一个类或接口 所以需要先定义类或者接口 本案例中定义一个接口
       new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类的show方法");
            }
        };
        //此时method方法中有 内容了,执行测试类 但是没有输出结果
}

想要多次调用匿名内部类的方法,多次重写匿名内部类并进行调用即可。

public class Outer {
    //匿名内部类是局部内部类的一种,所以需要在外部类的方法中书写
    public void method(){
        //要想实现匿名内部类方法的调用,匿名内部类的本质是 继承了类或接口的对象,所以可以直接匿名内部类.方法进行方法的调用。
        new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类的show方法");
            }
        }.show();
        new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类的show方法");
            }
        }.show();
}
public class Outer {
    //匿名内部类是局部内部类的一种,所以需要在外部类的方法中书写
    public void method(){
        //但如果多次调用,则一直重复会造成代码复用性差,
        //new 是Inter(),并且又重写了show方法,则new Inter(){}整体可以认为是 接口Inter的实现类对象 那么可以按照多态的形式 将其赋值给Inter类接口。
        
        Inter i = new Inter(){
            @Override
            public void show() {
                System.out.println("匿名内部类的show方法");
            }
        };
        i.show();
    }
}
匿名内部类在开发中的使用

分析:
创建操作类对象,调用method方法
method方法 参数是接口名时,说明需要的是 接口实现类的对象

public class JumppingOperator {
    //接口的操作类
    public  void method(Jumpping j){
        //参数是接口名,说明需要的是 接口的实现类对象
        j.jump();
    }
}

这时 可以采用匿名内部类的形式,

new 类名/接口名(){
@Override
	重写方法;
}

匿名内部类的本质是:继承类或实现接口类的对象。

// 创建 JumppingOperator操作类 的 对象
JumppingOperator j = new JumppingOperator();
j.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("猫可以跳高了");
            }
        });

完整:

public interface Jumpping {
    //接口是抽象的内容,接口中定义方法修饰符不写 默认是public abstract
    void jump();
}
public class JumppingOperator {
    //接口的操作类
    public  void method(Jumpping j){
        //参数是接口名,说明需要的是 接口的实现类对象
        j.jump();
    }
}
// 测试类
public class JumppingDemo {
    public static void main(String[] args) {
        // 创建操作类对象,调用method方法
        // method方法 参数是接口名时,说明需要的是 接口实现类的对象
        // 这时 可以采用匿名内部类的形式,new 类名/接口名(){重写方法;}; 匿名内部类的本质是:继承类或实现接口的对象。
        JumppingOperator j = new JumppingOperator();
        Jumpping jj = new Cat();
        j.method(jj);//方法需要的 Jumpping接口的实现类对象

        System.out.println("--------------");
        //如果多次创建 Jumpping接口的 不同实现类 这样会产生多个类文件,只是用一次,会造成文件冗余。采用匿名内部类实现。
        j.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("猫可以跳高了");
            }
        });
        //其本质需要是的Jumpping接口实现类的对象,使用匿名内部类的形式,不用额外创建Jumpping的实现类。
    }
}

抽象类

概述

概念:
java中一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。

public abstract class Animal{
		public abstract void eat();
}

理解xhj:
①抽象类出现的原因:
创建父类的时候,通过多态形式(父类-子类)创建对象一般都是特殊的对象,且重写的内容都不一样;假设子类没有重写父类的方法,那么不同子类调用方法输出结果是都一样的,这显然和实际不符;所以要重写的方法不能由方法体,就需要被abstract修饰,定义为抽象方法;

②如果一个类中的方法需要定义为抽象方法,也就是被abstract修饰,那么它所在的类也需要被abstract修饰。

抽象类的特点

①抽象类和抽象方法必须使用abstract关键字修饰

public abstract class 类名{}
public abstract void 方法名();

② 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
理解:抽象类中 可以只有一般的成员方法,没有抽象方法

③ 抽象类不能实例化,参照多态的方式,通过子类对象实例化,这叫抽象类多态。

父类 对象名 = new 子类();

④抽象类的子类 会报错
解决方式:
①重写抽象类中的所有抽象方法;
②定义为抽象类;

理解:
①抽象类不能实例化,指的是不能直接实例化,但可以通过多态的方式进行实例化。
直接实例化(抽象类xxx ):xxx 对象名 = new xxx();

②抽象类中有构造方法,作用是:当抽象类通过多态实例化对象时,用于子类访问父类数据的初始化,即子类的构造方法会访问父类的构造方法,用于对子类所需父类数据的初始化。

备注2022/8/11
抽象方法的方法体必须被一对大括号包住;

抽象类的成员特点

① 成员变量
可以是变量,也可以是常量

final修饰的成员变量 不能被修改,即为常量。
private int age = 20; //变量
private final String cityContext = "北京";//常量

② 构造方法
有构造方法(无参、有参),但是不能直接实例化
作用:用于子类访问父类数据的初始化

构造方法:用于子类访问父类构造方法完成对它数据的初始化
public Animal(){ }
public Animal(int age){
    this.age = age;
}

直接实例化:
类名xxx 对象名 = new 类名xxx();

③ 成员方法
抽象方法:限定子类必须完成某些动作,即限定子类必须重写父类的某些方法
非抽象方法:提高代码复用性,由继承保证的。

非抽象两方法:
public void show(){
    age = 40;
    System.out.println(age);
    System.out.println(cityContext);
}

抽象方法:
public abstract void eat();

案例:猫和狗(抽象类版本)

// 127-test2
// 定义抽象类 以及 抽象方法 此是父类
public abstract class Animal {
    private String name;
    private int age;

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

    public abstract void eat();

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge() {
        return age;
    }
}

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public Cat(){}
    //子类创建有参构造方法,需要使用父类中的变量,必须使用父类的有参构造方法实现。super(参数1,参数2);
    public Cat(String name,int age){
        super(name,age);
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public Dog(){}
    public Dog(String name,int age){
        super(name,age);
    }
}

public class AnimalDemo {
    public static void main(String[] args){
        Animal ao = new Cat();
        ao.setName("加菲");
        ao.setAge(5);
        System.out.println(ao.getName() + ", " + ao.getAge());//加菲, 5
        ao.eat();//猫吃鱼

        ao = new Dog("贵宾",2);
        System.out.println(ao.getName() + ", "+ao.getAge());//贵宾, 2
        ao.eat();//狗吃骨头
    }
}

抽象类和普通类的区别

区别抽象类普通类
实例化为了被继承,不能实例化可以实例化一个对象
重写必须重写抽象类中的抽象方法可以选择重写父类方法、也可以直接调用父类方法
修饰符必须用abstract修饰不使用

相同点
普通类和抽象类都可以含有普通成员属性和普通方法;
普通类和抽象类都可以继承别的类或者被别的类继承;
普通类和抽象类的属性和方法都可以通过子类对象来调用;

基本类型包装类

概述

  • 基本类型包装类 = 基本数据类型封装成的对象;
  • 将基本数据类型封装成对象的好处:可以在对象中定义更多的功能方法操作该数据;
  • 常见的操作之一:用于基本数据类型与字符串之间的转换;

基本数据类型与对应的包装类

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

integer类

概念

  • 软件包是 java.lang 使用时不需要导包
  • integer类 间接 继承于 Number、Object
  • public final class Integer 说明Integer是最终类,不能被继承,也就是不能有子类
  • 包装一个对象中的原始类型int的值

常用方法

方法名说明
public Integer(int value)根据jint值创建Integer对象(过时)
public Integer(String s)根据String值创建Integer对象(过时)(这里的字符串只能是数组的不能是字符的)
public static Integer valueOf(int i)返回表示指定的int值的Integer实例
public static Integer valueOf(String s)返回一个保存指定String值的Integer对象
public int intValue()返回Integer的值作为int
Integer对象.intValue()
static int parseInt(String s )将字符串参数解析为带符号的十进制整数

案例:

// 130-test5
public class IntegerDEmo {
    public static void main(String[] args) {
        System.out.println("过时方式-----------");
        //通过构造方法,根据参数 创建Integer对象。
        Integer i = new Integer(100);
        System.out.println(i);

        Integer i2 = new Integer("100");
        System.out.println(i2);
        Integer i3 = new Integer("abc");
//        System.out.println(i3);//NumberFormatException
        //这里会报错

        System.out.println("推荐方式--------------");
        Integer i4 = Integer.valueOf(100);
        System.out.println(i4);
        Integer i5 = Integer.valueOf("563");
        System.out.println(i5);
        Integer i6 = Integer.valueOf("abc");
        System.out.println(i6);//NumberFormatException
    }
}

注意

  • 当使用Integer ii = Integer.valueof(String s)的时候,s参数只能是数字类型的字符串,也就是“12233”这种类型,否则会报错NumberFormatException

int和String的相互转换

int—String

String s = “” + int类型变量

public static String valueOf(int i)
返回int参数的字符串表示形式,该方法是String类中方法。

案例:

//int ---String
int number = 100;
//方式1:通过字符串加的形式
String s1 = "" + number;
System.out.println(s1);//100
//方式2:public static String valueOf(int i)
String s2 = String.valueOf(100);
System.out.println(s2);//100
String — int

String—Integer—int

String => Integer
	Integer i = Integer.valueOf(字符串)Integer => int
	int x = i.intValue();
	Integer基本类型包装类的对象.intValue() --》 把Integer类的对象转成int类型。

String – int

Integer.parseInt(String s)
public static int parseInt(String s)
将字符串解析为int类型,该方法是Integer类中的方法。

案例:

//String -- int
String s = "100";
// 方式1:String-Integer-int
Integer i = Integer.valueOf(s);
//public int intValue() Integer类中的方法
int x = i.intValue();
System.out.println(x);//100
//方式2:String -- int
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println(y);//100

案例:字符串中数据排序
需求:
有一个字符串,“91 27 46 38 50” 请写程序实现最终输出结果是“27 38 46 50 91”
关键点: 字符串–字符串数组–int类型数组–数据元素排序–字符串

分析理解:

1 定义一个字符串
2 得到字符串中的数字 组成一个数字数组 使用方法public String[] split(String regex)
	通过【字符串.split(regex:“分隔符”)】
3 把字符串数组中的每一个元素存储在int数组中
	通过for循环,实现遍历字符串数组中的每一个元素;
	方法public static int parseInt(String s):将字符串转为int类型。是Integer基础类型包装类中的;
	形式:int i = Integer.parseInt(String s)
4int数组进行排序
	使用方法Arrays.sort(数组名);
5 排序后的数组组成一个字符串
	使用StringBuilder类的对象中的方法append()方法。
	创建StringBuilder对象,使用对象.append(),然后再使用对象.toString()转为String类型。
// 131-test1
public class Deno1 {
    public static void main(String[] args) {
        //定义一个字符串
        String s1 = "91 27 46 38 50";
        //把字符串中的数字数据存储到一个int类型的数组中
        //得到字符串中的每一个数字数组public String[] split(String regex)
        //此方法需要通过字符串.split调用
        String[] arrStr = s1.split(" ");
/*        for(int i = 0; i<arrStr.length ; i++){
            System.out.println(arrStr[i]);
        }*/
        //定义一个int数组,把String数组中的每一个元素存储到int数组中
        //public static int parseInt(String s)是Integer基础类型包装类中的
        int[] arr = new int[arrStr.length];
        for (int i = 0; i <arrStr.length; i++){
            arr[i] = Integer.parseInt(arrStr[i]);
        }
        //对int数组进行排序
        Arrays.sort(arr);

        //对排序后的int数组中的元素进行拼接得到一个字符串,这里的拼接采用StringBuilder实现
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i<arr.length; i++){
            if(i == arrStr.length - 1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]).append(" ");
            }
        }
        String s2 = sb.toString();
        //输出结果
        System.out.println(s2);
    }
}

自动装箱和拆箱

概念:

  • 装箱:把基本数据类型转换为对应的包装类类型

手动装箱:

Integer i = Integer.valueOf(100);

自动装箱:

Integer ii = 100;
  • 拆箱:把包装类类型转换为对应的基本数据类型

手动拆箱:

ii = ii.intValue() + 100;
表示:手动拆箱 和 自动装箱 

ii.intValue() 手动拆箱,
Integer = int + int 自动装箱

自动拆箱:

ii += 200;
表示自动拆箱和自动装箱;

ii+200 Integer + 200 自动拆箱
ii = ii + 200 Integer = int 自动装箱

理解xhj:

Ingeter iii = null;
iii += 300;
//此时会报错NullPointerException

注意:
①在使用包装类类型的时候,如果做操作,最好先判断是否为null
②只要是对象,在使用前就必须进行不为null的判断;

接口

概述

接口用于描述系统对外提供的所有服务,因此接口中的所有成员常量和方法都必须是public类型;
java中的接口更多体现的是对行为的抽象。
接口(interface)和类(class)是并列的结构。

接口特点

  • 接口用关键字interface 修饰
public [abstract] interface 接口名{}
  • 类实现接口用implements表示
public class 类名 implements 接口名{}

备注2022/8/11
java接口的修饰符可以为public abstract

  • 接口不能直接实例化
    直接实例化(接口名 对象 = new 接口名{})
    需要:参照多态方式,通过实现类对象进行实例化,这叫接口多态。

  • 接口的实现方式两种
    ①重写接口中的所有抽象方法;
    ②接口的实现类是抽象类;

理解xhj:
①接口是抽象内容,所以接口中可以有抽象方法;

案例:

// 127-test3
// 定义一个接口
// 接口是一个抽象内容,所以接口中可以有抽象方法。
public interface Jumpping {
    // 接口中可以定义抽象方法
    public abstract void jump();
}
// 类和接口的关系是 类实现接口 = 类名 implements 接口名
public class Cat implements Jumpping {
    // Cat报错 因为:没有重写接口Jumpping中的抽象方法
    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
public abstract class Dog implements Jumpping {
    //类实现接口 报错
    // 解决方式:①重写接口中的抽象方法②将类定义为抽象类,但是后续继承此类的子类还是需要重写抽象方法的。
}
public class JuppingDemo {
    public static void main(String[] args) {
        //接口的实例化
//        Jumpping j = new Jumpping();
        //接口是抽象内容,不能直接进行实例化,可以通过多态实现实例化
        Jumpping j = new Cat();
        j.jump();
    }
}

接口的成员特点

成员变量

  • 只能是常量,默认修饰符:public static final

构造方法

  • 接口没有构造方法,因为接口主要是对行为进行抽象的,没有具体存在
  • 一个类如果没有父类,默认继承自Object类
  • 接口实现类的构造方法 需要调用接口的构造方法,但接口没有,调用的是Object类的构造方法。
//定义接口的实现类
public class InterImpl implements Inter {
//接口类的定义实际上等价于
//public class InterImpl extends Object implements Inter{
        public InterImpl(){
            // 接口实现类的构造方法 会自动调用接口的无参构造方法,但接口又没有无参构造方法,它调用的是Object类的无参构造方法
            super();
        }
}

成员方法

  • JDK7.0之前 :只能是抽象方法,默认修饰符:public abstract
  • JDK7.0之后:可以有抽象方法、静态方法、默认方法。

理解xhj:

  • 类Object是类层次结构的根,每个类都有Object作为超类(父类、基类),所有对象(包括数组)都实现了这个类的方法。
  • 接口实现类的构造方法 会自动调用 接口的无参构造方法,但接口又没有无参构造方法,它调用的是Object类的无参构造方法。

案例:猫和狗
需求:采用抽象类和接口来实现猫狗案例,并在测试类中进行测试。

注意xhj:

抽象类:
通过子类继承抽象类实例化的对象,只能调用抽象类中的抽象方法
接口:
通过接口实现类实例化的对象,只能调用接口中的抽象方法

备注2022/8/11
多态形式创建对象:编译看左边、执行看右边。

一个类 = 抽象类的子类、接口的实现类

public class 子类 extends 抽象类 implements 接口{}
// 127-test5
// 创建接口
public interface Jumpping {
    public abstract void jump();
}

// 抽象类
public abstract class Animal {
    private String name;
    private int age;

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

    public Animal() {
    }

    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 abstract void eat();
}

// 接口实现类
public class Cat extends Animal implements Jumpping{
    public Cat(){}
    public Cat(String name,int age){
        super(name,age);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}
// 测试
public class JumppingDemo {
    public static void main(String[] args) {
        // 接口多态创建对象
        Jumpping j = new Cat();
        j.jump();
//        j.eat();//报错
 // 采用多态的形式创建对象,成员方法的调用 编译要看等号左侧,执行要看等号右侧
        // 编译期间,左侧的Jumpping接口并没有eat抽象方法,所以编译会报错。
        System.out.println("-----------");

		// 抽象类多态创建对象
        Animal ao = new Cat();
        ao.setName("加菲");
        ao.setAge(2);
        System.out.println(ao.getName() + ", " + ao.getAge());
        ao.eat();
//        ao.jumpping();//报错。

        //通过抽象类实例化的对象,只能调用抽象类中的抽象方法
        //通过接口实例化的对象,只能调用接口中的抽象方法

    }
}

类和接口的关系

①类和类的关系
继承关系,只能单继承,但是可以多层继承

public class Granddad{}
public class Dad extends Granddad{}
public class Son extends Dad{}
多层继承,Son类也继承了GranddadDad中的内容。

②类和接口的关系
实现关系:可以单实现,也可以多实现;一个类同时实现多个接口
继承关系:可以继承一个类的同时实现多个接口;

多个接口的实现
public class InterImpl implements Inter1,Inter2,Inter3{}
public class 类名       implements 接口名1,接口名2,接口名3{}
继承一个类的同时 实现多个接口
public class InterImpl extends InterClass implements Inter1,Inter2,Inter3{}
public class   子类名     extends  父类名   implements 接口名1,接口名2,接口名3{}

③接口和接口的关系
继承关系,可以单继承,也可以多继承

接口与接口直接关系:单继承、多继承都可以。
public interface Inter1 extends Inter2,Inter3{}
public interface 接口名1 extends 接口名2,接口名3{}

抽象类和接口的区别

类别抽象类接口
成员区别变量、常量;构造方法;
抽象方法,非抽象方法
常量;
jdk1.7之前抽象方法;jdk1.7之后加了默认方法、静态方法
关系区别类与类:继承,单继承
类与接口:实现,单实现、多实现
接口与接口:继承,单继承、多继承
设计理念区别对类抽象,包括属性、行为对行为抽象,主要是行为
添加新的方法给抽象类添加新方法,提供默认实现,就不需要改现有代码接口中添加新方法,必须修改该接口的实现类

理解xhj:
门和报警的关系:
门有开和关两属性,现在有些门具有报警功能,具体的设计。
①都采用抽象类的方式,那么开门、关门、报警这些方法按照抽象方法写入抽象类中,继承抽象类的子类都具备了报警方法,但有些门可能不具备报警功能。
②都采用接口的形式。同理接口的实现类都具有报警方法,但是有些门可能不具备报警功能。
③最好的方式是:开门、关门采用抽象类定义,报警使用接口定义。

案例:运动员和教练

需求:
有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。分析那些具体类、那些抽象类、那些接口,并用代码实现。

分析:

从具体到抽象》
具体的类:乒乓球运动员、篮球运动员、乒乓球教练、篮球教练
抽象类: ① 运动员类  教练类
        ② 人类
接口》
学习英语;

抽象类:

// 127-test6
public abstract class Coach extends Person {
    public Coach(){}
    public Coach(String name,int age){
        super(name,age);
    }

    public abstract void teach();
}
//抽象人类
public abstract class Person {
    public String name;
    public int age;

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

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }

    public abstract void eat();
}
public abstract class Player extends Person {
    //继承抽象类 会报错;解决方式①定义子类为抽象类②重写抽象类父类的所有抽象方法

    public Player(){}
    public Player(String name,int age){
        super(name,age);
    }
    public abstract void study();
}

接口:

//说英语接口
public interface SpeakEnglish {
    public abstract void speak();
}

具体类:(篮球)

// 篮球教练类 具体类
public class BasketballCoach extends Coach {

    // 由于其继承的是Coach 抽象类,所以需要重写其中的抽象方法;
    // Coach继承于 Person 抽象类,所以也需要重写其中的抽象方法。

    @Override
    public void eat() {
        System.out.println("篮球教练饮食健康");
    }

    @Override
    public void teach() {
        System.out.println("篮球教练教运球和投球");
    }

    //两个构造方法
    public BasketballCoach() {
    }

    public BasketballCoach(String name, int age) {
        super(name, age);
    }
}
// 篮球运动员类 具体类
public class BasketballPlayer extends Player {
    @Override
    public void study() {
        System.out.println("篮球运动员学习运球和投篮");
    }

    @Override
    public void eat() {
        System.out.println("篮球运动员吃蛋白粉");
    }

    public BasketballPlayer() {
    }

    public BasketballPlayer(String name, int age) {
        super(name, age);
    }
}

具体类:(乒乓球)

// 乒乓球教练 具体类
public class PingPangCoach extends Coach implements SpeakEnglish{
    @Override
    public void teach() {
        System.out.println("乒乓球教练教接球和罚球");
    }

    @Override
    public void eat() {
        System.out.println("乒乓球教练吃维生素含量多的饭");
    }

    @Override
    public void speak() {
        System.out.println("乒乓球教练说英语");
    }

    public PingPangCoach() {
    }

    public PingPangCoach(String name, int age) {
        super(name, age);
    }
}
// 乒乓球运动员类 具体类
public class PingPangPlayer extends Player implements SpeakEnglish {
    @Override
    public void speak() {
        System.out.println("乒乓球运动员学英语");
    }//重写接口SpeakEnglish中的抽象方法

    @Override
    public void study() {
        System.out.println("乒乓球运动员学习接球和打球");
    }//重写抽象类Player中的抽象方法

    @Override
    public void eat() {
        System.out.println("乒乓球运动员吃蛋白棒");
    }//重写抽象类Player中继承的抽象类Person中的抽象方法eat

    public PingPangPlayer() {
    }

    public PingPangPlayer(String name, int age) {
        super(name, age);
    }

}

测试:

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

        PingPangPlayer ppp = new PingPangPlayer();
        ppp.setName("马龙");
        ppp.setAge(35);
        System.out.println(ppp.getName() + ", " + ppp.getAge());
        ppp.eat();//Person抽象类的抽象方法
        ppp.study();//Player抽象类的抽象方法
        ppp.speak();//SpeakEnglish接口的抽象方法
        System.out.println("---------------");

        BasketballPlayer bbb = new BasketballPlayer("姚明",45);
        System.out.println(bbb.getName() + ", " + bbb.getAge());
        bbb.eat(); //Person抽象类的抽象方法
        bbb.study();//Player抽象类的抽象方法
//        bbb.speak();//报错,BasketballPlayer类中没有 speak方法
    }
}

接口组成更新

接口组成:
常量 public static final(修饰符可省略);抽象方法 public abstract(修饰符可省略);默认方法(java8);静态方法(java8);私有方法(java9);

接口中的默认方法

格式:

public default 返回值类型 方法名(参数列表){}
其中public可以省略
案例:
// public default void show3(){}

实现类重写默认方法的格式:
@Override
public 返回值类型 方法名(参数列表){}

注意事项:

  • 在接口中实现抽象方法的升级(再添加抽象方法),使用默认方法升级,接口的实现类可以重写默认方法、也可以不重写。
  • public 可以省略,default不可以省略。
  • 一个实现类 不能同时实现两个具有相同默认方法的接口。

代码:

package itiheima312.test11;

public interface MyInterface {
    void show1();
    void show2();
    * 证明接口中添加抽象方法 如果是默认方法则实现类不需要修改;不是则需要修改实现类
//    void show3();
    * 接口中添加抽象方法,实现类如果没有重写该方法,实现类会报错。
    default void show4() { }
    * 接口中添加默认方法,实现类没有重写该方法也不会报错。
}

public class MyInterfaceImplOne implements MyInterface,MyInterface2 {
    @Override
    public void show1() {
        System.out.println("One show1");
    }
    @Override
    public void show2() {
        System.out.println("One show2");
    }
}
// 测试代码
public class MyInterfaceDemo {
    public static void main(String[] args) {
        // 按照多态的形式创建对象
        MyInterfaceImplOne mio = new MyInterfaceImplOne();
        mio.show1();
        mio.show2();
    }
}

public interface MyInterface2 {
    void method();
    default void show4(){};
    * 接口MyInterface2 和 接口 MyInterface 有相同的默认方法show4 所以同时实现这两个接口的类会报错。
}

接口中的静态方法

格式:

[public] static 返回值类型 方法名(参数列表){}
案例:
// public static void show(){}

注意:

  • 接口的实现类对象 可以调用 抽象方法、默认方法;
  • 当实现类 实现了 两个接口,且这两个接口都有静态方法method,那么使用 实现类对象.method 调方法就不知道 调的是哪个方法,所以接口中的静态方法只能用 接口名.方法名 调用;
  • public可以省略,static 不能省略。

代码:

package itiheima312.test12;

public interface Inter {
    void show(); // 抽象方法

    default void  method(){ // 默认方法
        System.out.println("Inter 中的默认方法启动了");
    }
    static void test(){ //静态方法
        System.out.println("Inter 中的静态方法启动了");
    }
}

public interface Inter2 {
    void show2(); // 抽象方法
    default void method(){ // 默认方法
        System.out.println("Inter2 中的method方法启动了");
    }
}

* 一个实现类 不能继承两个具有相同默认方法的接口
/*public class InterImpl implements Inter,Inter2{
    @Override
    public void show2() {
        System.out.println("InterImpl 中的show2方法实现了");
    }*/
    
public class InterImpl implements Inter{
    @Override
    public void show() {
        System.out.println("InterImpl 中的show方法实现了");
    }
}

public class InterDemo {
    public static void main(String[] args) {
        InterImpl ii = new InterImpl();
        ii.show();
        ii.method();
        * 报错 这个在编译阶段就会报错。
        * 接口中的静态方法调用 接口名.方法名
//        ii.test();
        Inter.test(); // 使用 接口.静态方法 实现调用
    }
}

接口中的私有方法

出现原因:
当两个默认方法或者静态方法中包含一段相同的代码实现时,会将相同的代码抽取成一个共性方法,不让别人使用,用私有给藏起来。

格式:

格式1private 返回值类型 方法名(参数列表){}	
格式2private static 返回值类型 方法名(参数列表){}	

注意事项:

  • 默认方法可以调用私有的静态方法和非静态方法;
  • 静态方法只能调用私有的静态方法;

代码:

package itiheima312.test13;

public interface Inter {
    default void show1(){
        System.out.println("show1 start");
//        System.out.println("you are my pretty sunshine");
//        System.out.println("All things come to someone who wait");
        method();
        System.out.println("show1 end");
    }
    default void show2(){
        System.out.println("show2 start");
//        System.out.println("you are my pretty sunshine");
//        System.out.println("All things come to someone who wait");
        method();
        System.out.println("show2 end");
    }
    static void method1(){
        System.out.println("method1 start");
//        System.out.println("you are my pretty sunshine");
//        System.out.println("All things come to someone who wait");
        method();
        System.out.println("method1 end");
    }
    static void method2(){
        System.out.println("method2 start");
//        System.out.println("you are my pretty sunshine");
//        System.out.println("All things come to someone who wait");
        method();
        System.out.println("method2 end");
    }
    private static void method(){
        System.out.println("you are my pretty sunshine");
        System.out.println("All things come to someone who wait");
    }
}

// 测试类。
public class InterDemo {
    public static void main(String[] args) {
        InterImpl i = new InterImpl();

        i.show1();
        System.out.println("----------");
        i.show2();
		
        System.out.println("----------");
        Inter.method1();
        System.out.println("-------------");
        Inter.method2();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值