java面向对象---final、抽象类和抽象方法、接口

1.final

【1】修饰变量:

(代码分析)

package com.mxdx9;


/**
 * @Auther:雨天_
 * @Date: 2022/4/20 - 04 - 20 - 9:39
 * @Descroption: com.mxdx9
 * @version:1.0
 */
public class Test {
    //这是一个main方法
    public static void main(String[] args) {
        //第一种情况
        //final修饰一个变量,变量的值不可以改变,这个变量也变成了一个字符常量,规定:修饰的名称大写
        final int D = 20;//final修饰基本数据类型
        //D = 90;报错,不可以修改值
        //第二种情况
        final Cat c = new Cat();//final修饰引用数据类型,地址值不可以改变
        //c = new Cat();----->地址值不可以更改
        //c对象的属性依然可以改变
        c.age = 19;
        c.weight = 9;
        //第三种情况
        final Cat c2 = new Cat();
        a(c2);
        //第四种情况
        b(c2);
    }
    public static void a(Cat c){
        c = new Cat();
    }

    public static void b(final Cat c){//c被final修饰,指向不可以改变
            //c = new Cat();
    }

}
package com.mxdx9;

public class Cat {
    int age;
    double weight;
}

【2】修饰方法:

final 修饰方法,这个方法不能被该类的子类重写

 【3】修饰类:

final 修饰类,代表没有子类,该类不可以被继承。

类被 final 修饰,里面的类没有必要被 final 修饰(final 可以省略不写)

 【4】案例:JDK 提供的 Math 类:由源码得;

(1)使用Math 类的时候无需导包,直接使用即可:

(2)Math 没有子类,不能被其他类继承

 (3)里面的属性全部被 final 修饰,方法也是被 final 修饰,只不过省略不写

原因:子类没有必要进行重写

(4)外界不可以创建对象

Math m = new Math();

 (5)Math 类中的所有属性,方法都被 static 修饰,则不能通过创建对象去调用,

类名. 方法名   类名. 属性名  去调用

2.抽象类和抽象方法

【1】抽象类和抽象方法的关系

抽象类中可以定义0-n个抽象方法

【2】抽象类的作用:

在抽象类中定义抽象方法,目的是为子类提供通用的模板

子类在定义的模板的基础上进行开发,先重写父类的抽象方法,然后可以扩展子类,抽象类避免了子类设计的随意性。通过抽象类,对子类进行某种程度上的限制。

【3】代码示例;

package com.mxdx9;

/**
 * @Auther:雨天_
 * @Date: 2022/4/20 - 04 - 20 - 12:07
 * @Descroption: com.mxdx9
 * @version:1.0
 */
    //4.一个类中如果有抽象方法,那么这个类也要变成抽象类
    //5.一个抽象类中可以有0-n个抽象方法
public abstract class Person {
    //1.在一个类中,有一类方法,子类对这个方法满意,无需重写,直接使用
    public void say(){
        System.out.println("我会说话");
    }
    //2.在一个类中,会有一类方法,子类对这个方法不会满意,会进行重写
    //3,一个方法的方法体去掉,被 abstract 修饰,那么这个方法就变成了一个抽象方法
    public abstract void sleep();
    public abstract void study();
}

    //6.抽象类可以被其他类继承:
    //7.一个类继承一个抽象类,那么这个类可以变成一个抽象类
    //8.一般子类不会 + abstract 修饰,一般会让子类重写父类中的抽象方法
    //9,子类重写抽象类,必须重写全部的抽象方法
    //10.子类未重写全部的抽象方法,子类也可变成一个抽象类
class Student extends Person{
    @Override
        public void sleep() {
        System.out.println("我喜欢在家里睡觉");
    }

        @Override
        public void study() {
            System.out.println("我喜欢学习");
        }
}

class Demo{
    //这是一个main方法
    public static void main(String[] args) {
        //11。创建抽象类的对象:----->抽象类不可以创建对象
        //Person p = new Person();

        //12.创建子类对象:
        Student s = new Student();
        s.sleep();
        s.study();
        s.say();

        //13.多态的写法:父类引用指向子类对象
        Person p = new Student();
        p.say();
        p.study();
        p.sleep();
    }
}

【4】例题:

(1)抽象类不能创建对象,那么抽象类中是否有构造器?

抽象类中一定有构造器。构造器的作用:给子类初始化对象的时候先用 super 调用父类的构造器。

(2)抽象类是否可以被 final 修饰?

抽象类不能被 final 修饰,抽象类是为了给子类继承用的。一个类被 final 修饰就没有子类,不存在继承。

3.接口

【1】声明格式:

【2】代码示例:

package com.mxdx.Test01;

    /*
    1.类是类,接口是接口,是同一层次的概念
    2.接口中没有构造器
    3.接口如何声名:interface
    4.JDK1.8之前,接口中只有两部分内收容
    (1)常量:固定修饰符。public static final
    (2)抽象方法:固定修饰符,public abstract
    PS:修饰符可以省略不写,IDE会自动补全
     */
public interface TestInterface {
    //常量
        public static final int NUM = 10;
        //抽象方法
        public abstract void a();
        public abstract void b(int num);
        public abstract int c(String name);
}

interface TestInterface01{
    void e();
    void f();
}
class Person{

}
    //5.类和接口的关系:实现关系。类实现接口
    //6.一个类实现一个接口,这个实现类要重写接口中的全部的抽象方法
    //7.没有全部重写抽象方法,那么这个类可以变成一个抽象类(一般不用)
    /*8.java有单继承,还有多实现
        一个类继承其他类,只能直接继承一个类
        这个类实现接口,可以实现多个接口
         */
    //9.先继承,再实现  extends Person implements TestInterface,TestInterface01
class Student extends Person implements TestInterface,TestInterface01{
        @Override
        public void a() {
            System.out.println("------1");
        }

        @Override
        public void b(int num) {
            System.out.println("------2");
        }

        @Override
        public int c(String name) {
            return 10;
        }

        @Override
        public void e() {
            System.out.println("------3");

        }

        @Override
        public void f() {
            System.out.println("------4");
        }
    }

    class Test{
        //这是一个main方法
        public static void main(String[] args) {
            //10.接口不能创建对象
            //TestInterface01 t = new TestInterface01();
            TestInterface01 t = new Student();//接口指向实现类-----> 多态

            //11.访问接口中的常量
            System.out.println(TestInterface.NUM);
            System.out.println(Student.NUM);
            Student s = new Student();
            System.out.println(s.NUM);
            TestInterface t1 = new Student();
            System.out.println(t1.NUM);
        }
    }

【3】接口的作用:

定义规则。与抽象类不同,它是接口不是类。

接口定义好规则,实现类负责实现。

【4】继承和实现

继承:子类对父类的继承

实现:实现类对接口的实现

【5】多态的应用场合:

(1)父类当做方法的形参,传入具体的子类的对象

(2)父类当做方法的返回值,返回的是具体的子类的对象

(3)接口当做方法的形参,传入具体的实现类的对象

(4)接口当作方法的返回值,返回的是具体的实现类的对象

【6】接口类和抽象类的区别:

 附:

JDK1.8之前,接口中只有两部分内收容
(1)常量:固定修饰符。public static final
(2)抽象方法:固定修饰符,public abstract

在JDK1.8之后,新增非抽象方法:

(1)被 public , default 修饰的非抽象方法

PS:1)default 修饰符必须加上,否则出错

        2)在实现类中重写接口中的非抽象方法,default 修饰符必须不能加,否则出错。

package com.mxdx.Test01;

public interface TestInterface02 {
    //常量
    public static final int NUM = 10;
    //抽象方法
    public abstract void a();
    //public abstract 修饰的非抽象方法
    public default void b(){
        System.out.println("TestInterface02-----b()----");
    }
}

class Test1 implements TestInterface02{
    public void c(){
        //用接口中的 b 方法
        b();//可以直接使用
        TestInterface02.super.b();
    }
    @Override
    public void a() {
        System.out.println("重写了a方法");
    }

    @Override
    public void b() {
        
    }
}

(2)静态方法:

PS:1)Static 不可以省略不写

         2)静态方法不能重写

package com.mxdx.Test01;

public interface TestInterface03 {
    //常量
    public static final int NUM = 10;
    //抽象方法
    public abstract void a();
    //public default 修饰的非抽象方法
    public default void b(){
        System.out.println("-------TestInterface03----b()----");
    }
    //静态方法
    public static void c(){
        System.out.println("TestInterface03中的静态方法");
    }
}

class Test3 implements TestInterface03{
    @Override
    public void a() {
        System.out.println("重写了a方法");
    }

    public static void c(){
        System.out.println("Test3中的静态方法");
    }
}

class A{
    //这是一个main方法
    public static void main(String[] args) {
        Test3 t3 = new Test3();
        t3.c();
        Test3.c();
        TestInterface03.c();
    }
}

问:为什么在接口中加入非抽象方法??

若接口中只能定义非抽象方法的话,那么修改接口中的内容对实现类的影响太大了,所有实现类都会受到影响。现今加入非抽象方法,对实现类没有影响,可直接调用

附:内部类:

1.成员内部类:

(代码示例)

package com.mxdx.Test01;

/**
 * 1.类的组成长:属性,方法,构造器,代码块(普通块,静态块,构造块,同步块),内部类
 * 2.一个类TestOuter01的内部的类SubTest叫内部类,内部类:SubTest  外部类:TestOuter01
 * 3.内部类:成员内部类(静态的,非静态的),局部内部类(位置;方法内,块内,构造器内)
 * 4.成员内部类:其中含有属性,方法,构造器    修饰符:default,public,protected.private.final.
 */
public class TestOuter01 {
    //成员内部类:
    public class D{
        int age = 20;
        String name;
        public void method(){
            //内部类可以访问外部类的内容
            //a();
            int age = 30;
            System.out.println(age);//30
            System.out.println(this.age);//20
            System.out.println(TestOuter01.this.age);
        }
    }

    //静态成员内部类:
    static class E{
        public void method(){
            //静态内部类中只能访问外部类中被static修饰的内容
            //System.out.println(age);
            //a();
        }

    }
    //属性
    int age = 10;
    //局部变量在方法中或者块中放置
    //方法
    public  void a(){
        System.out.println("这是a方法");
        {
            System.out.println("这是一个普通块");
            class B{

            }
        }
        class A{

        }
        //7.外部类想访问内部类的东西,需要创建内部类的对象然后调用
        D d = new D();//new D();出错,静态的不能访问非静态的东西
        System.out.println(d.name);
        d.method();
    }
    static {
        System.out.println("这是一个静态块");
    }
    {
        System.out.println("这是一个构造块");
    }
    //构造器
    public TestOuter01(){
        class C{

        }
    }

    public TestOuter01(int age){
        this.age = age;
    }
}

class Demo{
    //这是一个main方法
    public static void main(String[] args) {
        //创建外部类的对象
        TestOuter01 t1 = new TestOuter01();
        t1.a();
        //创建内部类的对象
        //静态的成员内部类创建对象
        TestOuter01.E e = new TestOuter01.E();
        //非静态成员内部类创建对象
        //错误:TestOuter01.D d = new TestOuter01.D();
        TestOuter01 t = new TestOuter01();
        TestOuter01.D d =t.new D();
    }
}

2.局部内部类:

(代码示例)

package com.mxdx.Test02;

public class TestOuter {
    //这是一个main方法
    public void method(){
        //1.在局部内部类中访问的变量必须是被final修饰的
        final int num = 10;
        class A{
            public void a(){//若要在a中访问上面的num,上面的变量必须是被final修饰的
                //num = 20;若被final修饰,这个值便不能改变
                System.out.println(num);

            }
        }
    }
    //2.如果B在整个项目中只使用一次,那么就没有必要单独创建一个B类,使用内部类就可以
    public Comparable method2() {
        class B implements Comparable {
            @Override
            public int compareTo(Object o) {
                return 10;
            }
        }
        return new B();
    }

    public Comparable method3(){
        //3.匿名内部类
        return new Comparable() {
            @Override
            public int compareTo(Object o) {
                return 120;
            }
        };
    }
    public void Test(){
        Comparable com = new Comparable() {
            @Override
            public int compareTo(Object o) {
                return 120;
            }
        };
        System.out.println(com.compareTo("abc"));
    }
}

4.项目

【1】项目结构分析

 【2】父类子类创建:

package com.mxdx.Test03;

public class Pizza {
    // 属性
    private String name;//名称
    private int size;//大小
    private int price;//价格
    //方法
    public String getName() {
        return name;
    }

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

    public int getSize() {
        return size;
    }

    public void setSixe(int size) {
        this.size = size;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    //展示披萨信息
    public String showPizza(){
        return "披萨的名字是:"+name+",\n披萨的大小是:"+size+"寸,\n披萨的价格是"+price+"元";
    }

    //构造器
    public Pizza(){

    }

    public Pizza(String name, int size, int price) {
        this.name = name;
        this.size = size;
        this.price = price;
    }
}
package com.mxdx.Test03;

public class FruitsPizza extends Pizza{
    //属性
    private String burdening;

    public String getBurdening() {
        return burdening;
    }

    public void setBurdening(String burdening) {
        this.burdening = burdening;
    }

    //构造器
    public FruitsPizza(){

    }

    public FruitsPizza(String name, int size, int price, String burdening) {
        super(name, size, price);
        this.burdening = burdening;
    }

    //重写父类的showPizza方法:

    @Override
    public String showPizza() {
        return super.showPizza()+"\n 需要加入的水果是:"+burdening;
    }
}
package com.mxdx.Test03;

public class BaconPizza extends Pizza{
    //属性:
    private int weight;

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    //构造器:
    public BaconPizza(){

    }

    public BaconPizza(String name, int size, int price, int weight) {
        super(name, size, price);
        this.weight = weight;
    }

    //重写父类的showPizza方法:

    @Override
    public String showPizza() {
        return super.showPizza()+"\n 培根的克数是:"+weight+"克";
    }
}

【3】测试类逻辑以及创建

package com.mxdx.Test03;

import java.util.Scanner;

public class Test {
    //这是一个main方法
    public static void main(String[] args) {
        //选择
        Scanner sc = new Scanner(System.in);
        System.out.println("请选择你要购买的披萨。(1.培根披萨 2. 水果披萨):");
        int choice = sc.nextInt();//选择
        switch (choice) {
            case 1:
            {
                System.out.println("请录入培根的克数:");
                int weight = sc.nextInt();
                System.out.println("请录入披萨的大小:");
                int size = sc.nextInt();
                System.out.println("请录入披萨的价格:");
                int price = sc.nextInt();
                //将录入的信息封装为培根披萨的对象:
                BaconPizza bp = new BaconPizza("培根披萨",size,price,weight);
                System.out.println(bp.showPizza());
            }
            break;
            case 2:
            {
                System.out.println("请录入想加入的水果:");
                String Burdening = sc.next();
                System.out.println("请录入披萨的大小:");
                int size = sc.nextInt();
                System.out.println("请录入披萨的价格:");
                int price = sc.nextInt();
                //将录入的信息封装为水果披萨的对象:
                FruitsPizza fp = new FruitsPizza("水果披萨",size,price,Burdening);
                System.out.println(fp.showPizza());
            }
            break;
        }
        
    }
}

【4】工厂类的提取:

package com.mxdx.Test03;

import java.util.Scanner;

public class Test {
    //这是一个main方法
    public static void main(String[] args) {
        //选择
        Scanner sc = new Scanner(System.in);
        System.out.println("请选择你要购买的披萨。(1.培根披萨 2. 水果披萨):");
        int choice = sc.nextInt();//选择

        //通过工厂获取披萨:
        Pizza pizza = PizzaStore.getPizza(choice);
        System.out.println(pizza.showPizza());
    }
}
package com.mxdx.Test03;

import java.util.Scanner;
public class PizzaStore {
    public static Pizza getPizza(int choice){
        Scanner sc = new Scanner(System.in);
        Pizza p = null;
        switch (choice) {
            case 1:
            {
                System.out.println("请录入培根的克数:");
                int weight = sc.nextInt();
                System.out.println("请录入披萨的大小:");
                int size = sc.nextInt();
                System.out.println("请录入披萨的价格:");
                int price = sc.nextInt();
                //将录入的信息封装为培根披萨的对象:
                BaconPizza bp = new BaconPizza("培根披萨",size,price,weight);
                p = bp;
            }
            break;
            case 2:
            {
                System.out.println("请录入想加入的水果:");
                String Burdening = sc.next();
                System.out.println("请录入披萨的大小:");
                int size = sc.nextInt();
                System.out.println("请录入披萨的价格:");
                int price = sc.nextInt();
                //将录入的信息封装为水果披萨的对象:
                FruitsPizza fp = new FruitsPizza("水果披萨",size,price,Burdening);
                p = fp;
            }
            break;
        }
        return p;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨天_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值