Java中的三大特性-封装,继承,多态

本文详细解释了Java中的封装、访问修饰符、构造方法、继承机制(包括super关键字)、多态、抽象类、final关键字、接口、向上转型和向下转型,以及instanceof关键字的使用。

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

封装

属性(成员变量的封装)

在没有封装之前

在一个类中书写属性(成员变量)的就是

语法格式

数据类型 属性名;

有了封装之后,

(1)需要在数据类型前加上private关键字进行修饰

(2)需要对封装的属性编写对应的set和get成员方法来对类的属性进行赋值和取值

类的构造方法

类的构造方法是伴随对象创建的过程对属性进行赋值

一个类中默认是有一个默认权限修饰符的无参构造方法,但是如果类中一旦编写了新的构造方法就会自动顶替掉原来的默认构造方法。(如果有另外的一个类继承了这一个类,那么子类就会报错,原因到后面的继承细讲)

而针对属性的set方法是必须作用到对象上,因为set方法本质上还是一个成员方法

this关键字

this关键字可以使用在构造方法中,还可以使用在普通方法中。

在构造方法中

public User {
    
    private int age;
    private String name;
    
    public User (){
        this( 23 , "chuyao" );
    }
    
    public User( int age , String name ){
        this.age = age;
        this.name = name;
    }
    
    public boolean equals ( User user ){
        if ( this.age == user.age && this.name.equals( user.name ) ){
            return true;
        }
        return false;
    }
}

(1)上述有参构造方法构造方法中的this关键表示当前对象。

(2)this关键字还可以调用本类的构造方法,可以在本类的一个构造方法使用this();调用其他的构造方法,但是其他的构造方法必须放在调用者的第一行

(3)this关键字在普通方法中也可以表示当前对象,如上述的equals方法

多类合作

一个类的对象引用可以当作另一个类的成员变量(属性)(两个类的关系是聚合关系,一个类中有了另一个类)

对象的引用可以作为另一个类的属性。

示例

public class City {
    private String name;
    private User user;
}

类City和类User的关系就是包含关系

继承

示例说明

class Animal {
    private String name;
    private int age;
    
    public Animal (){
        
    }
    
    public Animal ( Stirng name , int age ){
        this.name = name;
        this.age = age;
    }
    
    public void setName ( String name ){
        this.name = name;
    }
    
    public String getName(){
        return name;
    }
    public static int getSize(){
        reutrn 3;
    }
    public final int getOne(){
        return 1;
    }
    private int getTwo(){
        return 2;
    }
    
}

class Dog extends Animal {
    
}
(1)继承使用extends关键字,表示一个类继承了另一个类,在上例中Animal和Dog分别是超类和子类
(2)在有继承关系的两个类中,子类可以使用父类的被公开的和默认的权限修饰符修饰的属性和方法
(3)继承的两个类中,如果父类Animal没有无参构造方法,那么它的子类Dog就会报错,
因为子类继承父类,子类会有一个默认的无参构造方法去调用父类的无参构造方法,而现在父类没有无参构造方法,所以子类就会报错
要想解决这个子类因为父类的构造方法报错的问题
第一种,可以在父类中写一个无参构造方法
第二种,可以在子类的构造方法中使用super( 参数列表 )调用父类的有参构造方法,注意,这个super代码必须放在子类构造方法的第一行

单继承和多重继承

class A {
    
}
class B extends A {
    
}
class C extends B {
    
}

(1)java中支持单继承,即一个类只能继承另一个类,不能继承多个类

(2)但是java中支持多重继承,即一个类可以继承另一个类,另一个类还可以继承其他的类

继承的内存分析

在这里插入图片描述

class GrandFa {
    String name = "爷爷";
    String hobby = "喝茶";
}
class Father extends GrandFa {
    String name = "爸爸";
    int age = 22;
}
class Son extends Father {
    String name = "儿子";
}
`总结:当有继承关系时,当你实例化一个子类对象的时候,所有的父类对象也会被创建,并且会和子类对象在同一块内存区域中。``

## super关键字

```java
class Father {
    String name;
    private int age;
    
    public Father(){
        
    }
    
    public Father ( String name , int age ) {
        this.name = name;
        this.age = age;
    }
    
    public void setAge( int age ){
        this.age = age;
    }
    public int getAge(){
        return age;
    }
    
    public void eat(){
        sout("爸爸正在吃饭");
    }
    public static void sleep (){
        sout("爸爸正在睡觉");
    }
    public final void run (){
        sout("爸爸正在跑步");
    }
    private void cc(){
        sout("cc");
    }
}

class Son extends Father {
    private String school;
    public Son(){
        
    }
    
    public Son( String name , int age , String school ){
        super( name , age );
        this.school = school;
    }
    
    public void go( int speed ){
        // 方法体
    }
    public void go( String name ){
        // 方法体
    }
    @Override
    public void eat (){
        System.out.println("儿子正在吃饭");
    }
}

在具有继承关系的两个类中

(1)super关键字可以在子类的构造方法中通过super(参数列表)调用父类的构造方法

(2)可以在子类的构造方法中使用super关键字表示父类的对象。

方法重载(overload)和方法重写(override)

重载

是指在一个类中具有多个方法名相同,但是方法的参数列表不同的方法。如上边例子中Son类的go方法

(1)构造方法可以重载

(2)成员方法也可以重载

(3)静态方法也可以重载

(4)返回值类型对方法重载没有影响

(5)参数名对方法重载没有影响,形参而已,只是一个占位符

重写

在具有继承关系的两个类中,子类可以重写父类中的某些方法

(1)子类可以重写父类中没有被 private 或者 static或者final这三个关键字修饰的成员方法

(2)子类重写父类的方法,必须和父类方法的方法名一致,参数列表一致,返回值类型一致

(3)重写方法的权限修饰符不能低于父类方法的权限修饰符

抽象类

class Demo {
    
} 

abstract class A extends Demo{
     
}
abstract class B extends A {
    private int age;
    private String name;
    
    public B ( int age , String name ){
        this.age = age;
        this.name = name;
    }
    
    public void eat(){
        // 方法体
    }
    
    public abstract void sleep();
}

class C extends B {
    public void sleep(){
        System.out.println( "人在睡觉" );
    }
}

(1)抽象类需要使用abstract关键字修饰
(2)抽象类可以有属性
(3)抽象类可以有构造方法
(4)抽象类不可以实例化对象
(5)抽象类里边可以有普通方法
(6)抽象类里边可以有抽象方法,使用abstract关键字修饰,抽象方法没有方法体
(7)一个有抽象方法的类一定是一个抽象类
(8)一个抽象类可以继承另外一个抽象类
(9)一个抽象类可以继承一个子类
(10)一个普通类可以继承一个抽象类,这个类必须要实现它父类的抽象方法

final关键字

public final class D {
    private final String name = "构造";
    public final void eat(){
        final int age;
        age = 10;
        // 方法体
    }
}
(1)final关键字可以修饰属性(成员变量),成员变量必须在声明的时候就赋值,并且之后也不能改变了
(2)可以修饰局部变量,在声明的时候可以不赋值,但是在使用的时候必须赋值,且之后不能再改变它的值了
(3)可以修饰对象引用,但是这个对象引用必须指向内存中一个具体的对象,,且这个对象引用的值不能再被改变了
(4)再具有继承关系的两个类中,子类不能重写父类中被final关键字修饰的成员方法。
(5)一个类如果被final关键字修饰,那么这个类不能被继承,比如String类

接口

interface A{
    
}
interface B extends A{
    [public static final] String name = "狗蛋"
    [public abstract] void eat();
    default void test(){
        System.out.println( " 正在测试" );
    }
}
class C implements B{
    public void eat(){
        System.out.println( " 正在吃东西" );
    }
}
(1)接口使用interface关键字修饰
(2)接口里边可以有属性,但是默认被 public static final 这三个关键字修饰,是常量
(3)接口里边没有构造方法
(4)接口不可以实例化对象
(5)接口里边有方法,默认被 public abstract 关键字修饰,是抽象方法
(6)一个接口可以继承另一个接口
(7)一个类可以实现多个接口,使用implements关键字,接口之间使用逗号隔开
(8)一个类实现了接口,必须实现接口中所有的抽象方法
(9)java8之后接口中可以有用default关键字修饰的默认方法,可以有方法体

多态

同一个方法作用到同一类对象(1.多个类继承同一个超类 2.多个类实现了同一个接口)上,展现出不同的形态

class Father {
    public void eat(){
         System.out.println( " 爸爸正在吃东西" );
    }
}
class Son extends Father{
    public void eat(){
        System.out.println( "儿子正在吃东西" );
    }
}
class Daughter extends Father{
    public void eat(){
        System.out.println( "儿子正在吃东西" );
    }
}
interface A {
    
}
class B implements A {
    
}
class C implements A {
    
}
// 这时你可以在另一个类中用接口的引用指向(实现了这个接口)子类的对象
public class Test{
    public static void main ( String[] args ){
        // 下面这两种语法格式完全可以,没问题,不会报错
        // 如果接口中有抽象方法,那么就可以对接口调用抽象方法,最终会作用到子类对象上
        A b = new B();
        A c = new C();
    }
}

向上转型

用父类的对象引用指向子类的对象

Father father = new Son();

向下转型

现有向上桩型,再有向下转型

先用父类引用指向子类对象,然后再把父类引用转成子类引用

多态的转型问题

向上转型

本质:就是父类的引用指向子类的对象。

Father father = new Son();

小范围转大范围。(自动的)

父类的引用只能调用子类重写父类的方法。

父类的引用无法调用子类独有的方法,只能调用子类重写父类的方法

向下转型(现在不用了)(自己实践一下)

通过向下转型就可以调用子类独有的方法了

向下转型的时候,必须先有向上转型,然后再向下转型

(1)先把子类的对象赋给父类的对象引用(向上转型),先暂时让子类对象变成父类的对象。

(2)然后再把父类的引用强转成子类的引用。(注意一定要注意类型的准确,否则会爆出类型转换异常)

(3)举一个例子,有一个公共的超类,雇员类

普通雇员类继承雇员类

经理类继承雇员类

向上转型:

无论是用雇员类的对象引用指向子类的普通雇员类对象或者指向经理类对象都是自动的,可以的,不会报错

再去向下转型,(把父类 的引用转成子类的引用)

// 第一种
// 向上转型
Employee commonEmployee = new CommonEmployee();
// 向下转型()
CommonEmployee c1 = ( CommonEmployee ) commonEmployee;
以上这种写法没问题,不会报错,不会出现类型转换异常

第二种转型

// 向上转型
Employee manager = new Manager();
// 在向下转型,把父类的引用转成子类的引用
// 下面这个代码会报错,会输出无法把Manager转成CommonEmployee异常
CommonEmployee c2 = ( CommonEmployee )manger;

其实上面这种异常,就是什么啊。普通雇员类和经理类都是雇员类的子类,所以都可以被雇员类对象引用所引用。

但是。思考,如果用雇员类的引用指向经理类的对象,(这是向上转型),但是这时把这个雇员类的引用转成普通雇员类的引用。会报错。其实他就是把经理类对象转成普通雇员类对象。肯定会报错,难道经理是普通雇员吗?

// 成功转型
CommonEmployee =(向上转型)> Employee =(向下转型)> CommonEmployee
// 错误转型(会报错,类型转换异常)
Manager => Employee => CommonEmployee

instanceof 关键字

语法格式

对象引用 instanceof 类型

如果对象引用是类型或者类型的子类的对象,返回true

否则返回false

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值