chapter8 三大特性

本文深入探讨了面向对象编程的三大特性——封装、继承和多态,并通过实例展示了如何在Java中实现这些特性。同时,讲解了构造器、权限修饰符以及方法的重写。此外,还涉及到了类与类之间的关系,如继承、实现、关联和聚合。最后,讨论了简单工厂设计模式和Java中的final关键字,以及接口和内部类的相关概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三大特性

封装

public class Girl {
    private int age;
    //读取年龄
    public int getAge(){
        return age;
    }
    //设置年龄
    public void setAge(int age){
        if(age>=30){
            this.age=18;
        }else{
            this.age=age;
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Girl g=new Girl();
        g.setAge(33);
        g.getAge();
        System.out.println(g.getAge());//输出18
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对于定义的构造器,如果修改了get set方法,那么构造器内部也需要修改

继承

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

extends 关键字

ublic class Person {
    //属性
    private int age;
    private String  name;
    private double hight;

    //getter-setter方法

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public double getHight() {
        return hight;
    }

    public void setHight(double hight) {
        this.hight = hight;
    }
    //方法
    public void eat(){
        System.out.println("eat");
    }
    public void sleep(){
        System.out.println("sleep");

    }
    public void yell(){
        System.out.println("yell");

    }
}
public class Student extends Person{//子类Student继承 父类 Person
    //属性
    private int sno;

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }
    //方法
    public void study(){
        System.out.println("study");
    }
}

在这里插入图片描述
在这里插入图片描述

权限修饰符

在这里插入图片描述
default:缺省修饰符,不写就行 :权限到同一个包的其他类都可以访问
在这里插入图片描述

方法的重写

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重载和重写的区别

在这里插入图片描述
在这里插入图片描述

重写的返回值只有在引用数据类型是才是,基本数据类型不可以

super关键字

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
生成构造器可以使用alt+insert快捷键

继承条件下,构造方法是怎样执行的

在这里插入图片描述

Object类

在这里插入图片描述

toString()方法

在这里插入图片描述
在这里插入图片描述

IDEA快捷键重写toString()
在这里插入图片描述

equals()方法

instanceof 运算符或者关键字
在这里插入图片描述
在这里插入图片描述

快捷键生成equals
在这里插入图片描述

???向下转型,为了获取子类中特有的内容

object obj=new phone();
在这里插入图片描述

类和类的关系

在这里插入图片描述

package relationship;

public class girl {
    //属性
    String name;
    double weight;
    mom m;//将一个类作为另一个类的属性
    //mom m=new mom();

    //方法
    public  void love(boy b){//将一个类作为另一个类中的方法的形参
        System.out.println("in love with "+b.name);
        b.buy();
    }

    public void wechat(){
        m.say();
    }

    //构造器

    public girl(String name,double weight) {
        this.name = name;
        this.weight=weight;
    }
}
package relationship;

public class boy {
    //属性
    String name;
    int age;
    //方法
    public void buy(){
        System.out.println("buybuybuy");
    }

    //构造器

    public boy(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
package relationship;

public class mom {
    public void say(){
        System.out.println("listen to mom");
    }
}
package relationship;

public class test {
    public static void main(String[] args) {
        boy tom=new boy("tom",19);
        girl lili=new girl("lili",99.9);
        lili.love(tom);

        lili.m=new mom();//引用数据类型先初始化才能调用
        lili.wechat();
    }
}

类和类之间的关系:继承;实现;依赖(形参);关联(属性);聚合(属性);组合(属性)

多态

两种应用场景:父类做形参;父类做返回值

多态与属性无关,多态指的是方法的多态,而不是属性的多态

父类—》子类:继承

子类—》父类:泛化

package duotai;
public class animal {
    int age;
    public void shout(){
        System.out.println("animal");
    }
}
package duotai;
public class cat extends animal {
    public void shout(){
        System.out.println("cat");
    }

}
package duotai;
public class dog extends animal{
    public  void shout(){
        System.out.println("dog");
    }
}
package duotai;
public class pig extends animal{
    double weight;
    public void shout(){//重写父类animal的shout方法
        System.out.println("pig");
    }
    public void eat(){
        System.out.println("pig eat");
    }
}
package duotai;
public class girl {
    public void play(animal an){
        an.shout();//一个方法就够,这就是多态,不然要写跟猪狗猫玩的方法重载
    }
}
package duotai;
public class test {
    public static void main(String[] args) {
        girl g=new girl();
        dog d=new dog();
       
        pig p=new pig();

        animal an=d;//多态
        g.play(an);//输出dog
		
		cat c=new cat;//合并animal an2=new cat();
        animal an2=c;
        g.play(an2);//输出cat
        animal an3=p;
        g.play(an3);//输出pig
        
        pig p2=(pig)an3;//向下转型,是因为an只能访问animal中的东西,不能访问pig中的东西,转型之后才能访问

        p2.weight=60.8;
        p2.shout();//输出pig
        p2.eat();//输出 pig eat
    }
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

注意:多态可以提高扩展性,但是扩展性没有达到最好,以后我们会学习反射

多态与属性无关,与方法有关

左侧=编译期类型,右侧=运行期类型

内存分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

向上转型,向下转型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

简单工厂设计模式

在这里插入图片描述

package duotai;
public class petStore {//----》工厂类
    //方法:提供动物
    public static animal getAnimal(String petName){//加上static就可以用类名.方法名调用,
                                   //没加static就必须创建一个petStore对象然后通过对象.方法名调用
        animal an=null;//局部变量必须进行初始化
        if("cat".equals(petName))//petName.equals("cat")--->这样写容易发生空指针异常
            {
                an=new cat();
            }
        if("dog".equals(petName)){
            an=new dog();
        }
        return an;//多态的应用场景(二):父类当作方法的返回值,具体返回的是子类

    }
}
public class test {
    public static void main(String[] args) {
        girl g=new girl();
        animal a=petStore.getAnimal("cat");
        g.play(a);//输出cat
    }
}

final关键字/修饰符

final修饰变量,修饰类,修饰方法

1.修饰变量的四种情况

package com.msb;

public class teatFinal {
    public static void main(String[] args) {
        //第1种情况:
        //final修饰一个变量,变量的值不可以改变,这个变量也变成了一个字符常量,约定俗成的规定:名字大写
        final int A=10;//final修饰基本数据类型
        //A=20;报错:不可以修改值

        //第2种情况
        final Dog d=new Dog();//final修饰引用数据类型,那么地址值就不可以改变
        //d=new Dog();报错:因为地址值不可以改变
        //d对象的属性依然可以改变,只是栈里的地址值不能更改
        d.age=10;
        d.weight=15.6;
        
        //第3种情况
        final Dog d2=new Dog();
        a(d2);//这里不会报错,因为d指向的地址值是可以改变的,只有d2不可改变
        
        //第4种情况
        b(d2);

    }
    public static void a(Dog d){
        d=new Dog();
    }
    public static void b(final Dog d){
        //d=new Dog();报错:因为final修饰d之后,d的地址值不可以更改,所以不能再创建新的对象
    }
}
public class Dog {
    int age;
    double weight;
}

2.修饰方法,修饰类

在同一个源文件中,只能有一个类被public修饰,并且被public修饰的类名必须跟源文件一样
在这里插入图片描述

math类的说明

在这里插入图片描述

抽象类,抽象方法

package com.msb;

public abstract class chouxiang {
    //4.如果一个类中有抽象方法,那么这个类也必须使用abstract修饰,变成一个抽象类
    //5.一个抽象类中可以有0-n个抽象方法
    public void eat(){//1.在一个类中,会有一类方法,子类对这个方法非常满意,无需重写,直接使用
        System.out.println("喜欢吃饭");
    }
    //3.一个方法的方法体去掉,然后被abstract修饰,那么这个方法就变成了一个抽象方法
    public abstract void say();//2.在一个类中,会有一类方法,子类对这个方法永远不满意,会对这个方法进行重写
    public abstract void sleep();
}

//6.抽象类可以被其他类继承
//7.一个类继承一个抽象类,那么这个类也可以变成抽象类
//8.一般子类不会加abstract修饰,一般会让子类重写父类中的抽象方法
//9.子类继承抽象类,就必须重写全部的抽象方法
//10.如果子类没有重写父类全部的抽象方法,那么子类也可以变成一个抽象类,一般让子类重写全部的抽象方法
class Student extends chouxiang{
    @Override
    public void say() {

    }

    @Override
    public void sleep() {

    }
}

class Demo{
    public static void main(String[] args) {
        //11.创建抽象类的对象-----》抽象类不可以创建对象
        //chouxiang c=new chouxiang();报错
        
        //12.创建子类对象
        Student s =new Student();
        s.say();
        s.sleep();
        
        //13.多态的写法,父类引用指向子类对象
        chouxiang c=new Student();
        c.say();
        c.sleep();
    }
}

在这里插入图片描述

面试题

在这里插入图片描述

接口

package com.msb;
/*1.类是类,接口是接口,他们是同一层次的概念
 2.接口中没有构造器
 3.接口如何声明:interface
 4.在JDK1.8之前,接口中只有两部分内容:
 (1)常量:固定修饰符:public static final
 (2)抽象方法:固定修饰符:public abstract
 注意:修饰符可以省略不写,IDEA会自动补全,初学者建议写上,防止遗忘*/

import com.msb.jicheng.Person;

public interface TeatInterface {
    //常量
    public static final int NUM=19;

    //抽象方法
    public abstract void a();
    public abstract void b(int num);
    public  abstract int c(String name);
}
/*
5.类和接口的关系:实现关系,类实现接口
6.一旦实现一个接口,那么实现类要重写接口中的全部抽象方法
7.如果没有重写全部抽象方法,那么这个类可以变成一个抽象类
8.java只有单继承,Java还有多实现;一个类继承其他类,只能直接继承一个父类,但是实现类实现接口的话,可以实现多个接口
9.写法:先继承再实现*/
interface testInterface01{
    void d();
    void e();
}

class sky extends Person implements TeatInterface,testInterface01{
    @Override
    public void a() {
        
    }
    @Override
    public void b(int num) {
        
    }
    @Override
    public int c(String name) {
        return 0;
    }
    @Override
    public void d() {
        
    }
    @Override
    public void e() {

    }
}
class Test01{
    public static void main(String[] args) {
        //10.接口不能创建对象:
        //TeatInterface t=new TeatInterface();
        TeatInterface t=new sky();//接口指向实现类----》多态;也可以返回实现类---》多态

        //11.接口中常量如何访问
        System.out.println(TeatInterface.NUM);//(1)

        System.out.println(sky.NUM);//(2)

        sky s=new sky();//(3)
        System.out.println(s.NUM);

        TeatInterface t1=new sky();//(4)
        System.out.println(t1.NUM);
    }
}

在这里插入图片描述
在这里插入图片描述

JDK1.8之后的接口

在这里插入图片描述
在这里插入图片描述
包名和类名不能一样,包名一般小写,类名一般每个单词首字母大写,驼峰是前面小写后面大写

package com.msb.baoming;

public interface Interface {
    //常量
    public static final int NUM=10;
    //抽象方法
    public abstract void a();
    //被public default 修饰的非抽象方法
    public default void b(){//注意:1.default修饰符必须要加上,否则会出错
        System.out.println("被public default 修饰的非抽象方法");

    }
}
class Test00 implements Interface{
    public void c(){//用一下接口中的b非抽象方法
        b();//可以
        //super.b();不可以
        Interface.super.b();//可以
    }

    @Override
    public void a() {
        System.out.println("重写的 接口:Interface a方法");
    }

    @Override
    public void b() {
        System.out.println("实现类中要是想重写接口中的非抽象方法,那么default修饰符必须不能加,否则出错");
    }
}
package com.msb.baoming;

public interface TestInterface2 {
    //常量
    public static final int NUM=20;
    //抽象方法
    public void a();
    //非抽象方法
    public default void b(){
        System.out.println("被public default 修饰的非抽象方法");
    }
    //静态方法
    public static void c(){
        System.out.println("静态方法");
    }
}
class Demo implements  TestInterface2{
    @Override
    public void a() {
        System.out.println("重写的 接口:Interface a方法");
    }
    public static void c(){
        System.out.println("Demo 中的静态方法");
    }
}
class Adomo{
    public static void main(String[] args) {
        Demo d=new Demo();
        d.c();//执行的是Demo中的静态方法
        //静态方法不能重写,只有非静态方法才可以重写
        Demo.c();
        TestInterface2.c();
    }
}

在这里插入图片描述

内部类
package neibulei;
/*1.类的组成:属性,方法,构造器,代码块(普通块,静态块,构造块,同步块)
* 2.内部类:成员内部类和局部内部类(位置:方法内,块内,构造器内)
* 3.一个类的内部的类叫内部类
* 4.成员内部类:里面属性,方法,构造器等,修饰符可以是:private, default,protected,public,final,abstract
* 一般没有内部类再套内部类*/
public class TestOuter {
    //成员内部类
    public class De{
        int age=20;
        String name;
        public void method(){//5.内部类可以访问外部类的内容
            //System.out.println(age);
            //a();
            int age=30;
            //8.内部类和外部类属性重名时,如何进行调用
            System.out.println(age);//30
            System.out.println(this.age);//20
            System.out.println(TestOuter.this.age);//10
        }
    }
    //静态成员内部类
    static class Ef{
        //6.静态内部类中只能访问外部类中被static修饰的内容
        public void method(){
            //System.out.println(age);报错
            //a();报错

        }
    }
    //属性:
    int age=10;

    public void a(){
        System.out.println("这是a方法");
        {
            System.out.println("这是普通块");
            class Bc{//块内的局部内部类

            }
        }

        class Ab{//方法内的局部内部类

        }
        //7.外部类想要访问内部类的东西,需要创建内部类的对象,然后调用
        De d=new De();
        System.out.println(d.name);
        d.method();
    }
    //构造块
    {
        System.out.println("这是构造块");
    }
    //静态块
    static {
        System.out.println("这是静态块");
    }
    //构造器
    public TestOuter(){
        class Cd{//构造器内的局部内部类

        }

    }
    public TestOuter(int age){

    }
}
class Demo{
    public static void main(String[] args) {
        //创建外部类的对象
        TestOuter to=new TestOuter();
        to.a();

        //创建内部类的对象
        //静态的成员内部类创建对象
        TestOuter.Ef ef=new TestOuter.Ef();
        //非静态的成员内部类创建对象
        //TestOuter.De de=new TestOuter.De();报错;必须通过外部类才能创建
        TestOuter t=new TestOuter();
        TestOuter.De de=t.new De();

    }
}

局部内部类(朗木达表达式?后面再说)

package neibulei;

public class Nei {
    //1.在局部内部类中访问到的变量必须是被final修饰的
    public void method(){
        int num=10;
        class A{
            public void a(){
                System.out.println(num);
            }
        }
    }
    //2.如果类B在整个项目中只使用一次,那么就没有必要单独创建一个B类,使用内部类就可以了
    public Comparable method2(){
        class B implements Comparable{
            @Override
            public int compareTo(Object o) {
                return 100;
            }
        }
        return new B();//接口当作返回值,那么返回的必须是实现类的具体的对象,一个小的多态的应用
    }

    public Comparable method3(){
        //3.匿名内部类
        return new Comparable() {
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        };
    }

    public void method4(){
        Comparable com= new Comparable() {
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        };
        System.out.println(com.compareTo("abc"));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值