二.面向对象的三大特性,封装、继承、多态

本文深入解析Java的封装、继承、多态等核心概念,详细阐述内部类、抽象类及接口的使用,帮助读者掌握Java面向对象编程的关键技巧。

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

2.1 java里的封装

1.封装的概念
将类的信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
2.封装的好处
只能通过规定的方法访问数据,隐藏类的实现细节,方便修改和实现
3.封装的实现步骤
a.修改属性的可见性  -private修饰符
b.创建getter/setter方法 -用于属性的读写
c.在getter/setter中加入属性控制语句

2.2 java中的包

1.包的作用
管理java文件,解决同文件冲突问题
2.系统中的包  
java.lang.*  包含java语言基础的类
java.util.*   包含java语言的各种工具类
java.io.*  包含输入输出的类
3.包的使用
通过Import关键字,在某个文件使用其他文件的类

2.3 java中的访问修饰符

1.访问修饰符的作用
可以修饰方法和属性的访问范围

2.访问修饰符总结
修饰符        本类    同包    子类    其他(其他包)
默认            1            1             0           0
private          1        0           0          0
protected      1        1          1          0
public          1          1           1           1

一般来说,我们的类属性一般声明为Private,方法一般声明为public的

2.4 java中的内部类

1.什么是内部类?
即一个类中还定义了一个类,称之为内部类

2.内部类的作用
按照常理,我们定义类的时候都是相互独立的,为什么有内部类的产生呢?
内部类提供了更好的封装性,可以把内部类隐藏在外部类之内,不允许同一个包的其他文件访问
内部类的方法可以直接访问外部类的所有数据,包括私有数据
内部类所实现的功能外部类同样可以实现,只是有时我们使用内部类更方便
3.内部类的分类
成员内部类
静态内部类
方法内部类
匿名内部类

**4.关于成员内部类
 

//外部类Outer
public class Outer{

    //外部类的私有属性name
    private String name = "imooc";

    //外部类的成员属性
    int age = 20;

    //成员内部类Inner
    public class Inner {
        String name = "爱慕课";
        //内部类中的方法
        public void show() {
            System.out.println("外部类中的name:" +Outer.this.name                  );
            System.out.println("内部类中的name:" +name                  );
            System.out.println("外部类中的age:" + age);
        }
    }

    //测试成员内部类
    public static void main(String[] args) {

        //创建外部类的对象
        Outer o = new Outer ();

        //创建内部类的对象
        Inner inn = o.new Inner()       ;

        //调用内部类对象的show方法
        inn.show();
		/*        输出结果:
        外部类中的name:imooc
        内部类中的name:爱慕课
        外部类中的age:20*/
    }
}

**需要注意的几点:
*成员内部类可以直接访问外部类的所有方法属性,包括私有的
*定义了成员内部类之后,必须使用外部对象来创建内部类对象,而不能直接new 一个内部类对象
*编译完成后,会产生两个class文件,内部类的.class文件总是 :外部类$内部类.class
*外部类不能直接访问内部类的方法和成员,可以先创建内部类对象然后对内部类的成员和方法进行访问
*如果外部类和内部类拥有同样的变量或者方法,内部类默认访问自己的变量和方法,如果要访问外部类的方法或者成员可以使用this关键字
 

5.关于静态内部类

//外部类
public class StaticOuter {

    // 外部类中的静态变量score
    private static int score = 84;

    // 创建静态内部类
    public    static      class SInner {
        // 内部类中的变量score
        int score = 91;

        public void show() {
            System.out.println("访问外部类中的score:" +     StaticOuter.score       );
            System.out.println("访问内部类中的score:" + score);
        }
    }

    // 测试静态内部类
    public static void main(String[] args) {
        // 直接创建内部类的对象

        SInner si =new SInner();
        // 调用show方法
        si.show();
    }
}

静态内部类是由static修饰的内部类
**静态内部类不能直接访问外部类的非静态成员变量,但可以通过new 外部类().变量 访问
如果外部类的静态成员变量与内部类成员变量相同,那么在内部类中可以通过 外部类.静态成员变量访问
如果外部类的静态成员变量与内部类成员变量不相同那么可以直接调用外部成员的静态变量
**创建静态内部类对象,不用通过外部类,直接new 内部类名()创建

6.关于方法内部类

//外部类
public class MethodOuter {

    private String name = "爱慕课";

    // 外部类中的show方法
    public void show() {
        // 定义方法内部类
        class MInner {
            int score = 83;
            public int getScore() {
                return score + 10;
            }
        }

        // 创建方法内部类的对象
        MInner mi=new MInner();

        // 调用内部类的方法
        int newScore =mi.getScore();

        System.out.println("姓名:" + name + "\n加分后的成绩:" + newScore);
    }

    // 测试方法内部类
    public static void main(String[] args) {

        // 创建外部类的对象
         MethodOuter mo = new MethodOuter();

        // 调用外部类的方法
        mo.show();
    }
}

方法内部类就是内部类定义在外部内的方法中
方法内部类只在该方法内部可见,即只能在该方法中使用
**注意:由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
 

2.5 java中的继承

1.继承的概念
继承是类与类的一种关系,是一种 is a 关系

2.继承的好处
拥有了父类的所有属性和方法(private不能继承)
实现代码复用

3.方法重写
如果子类对继承的父类方法不满意,是可以重写父类继承方法的,当调用方法的时候会优先调用子类的方法

4.继承的初始化顺序
先初始化父类再初始化子类
先执行初始化对象中的属性,再执行构造方法中的初始化

5.java继承中final关键字的使用
*final可以修饰类,方法,变量;表示最终的含义
*修饰类的时候,该类不允许被继承
*修饰方法的时候,该方法不允许被重写
**修饰属性的时候,则该类的属性不会进行隐性的初始化(类的初始化属性必须有值)或在构造方法中赋值(两者只能选其一)
*final修饰变量,则该变量的值只能赋值一次,即变为常量

6.java中super的使用
在对象的内部使用,表示父类对象
可以通过super.变量/方法调用
当super在构造方法中时:
一般来说,当子类继承父类时,当我们没有写父类的构造方法时,则系统会默认子类的构造方法中会隐式加入父类的无参构造方法
如 super(); 如果显示的调用构造方法,那么该方法必须在子类构造方法的第一行
注意:如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法时,编译就会报错
 

7. java中object类
object类是所有类的父类,当然object中的方法也适用于任何子类,比如
1)toString()方法,使用场景:当我们将一个对象直接输出的时候:

public class People {
    private int age=25;
    private String sex="男";
    public static void main(String[] args) {
        People people=new People();
        System.out.println(people);

        //输出结果为 People@4554617c  即对象在内存中的地址   为hashcode 即哈希码(由hash算法生成,用来唯一区分一个对象的)
    }
}

但是我们并不想输出该对象的地址,而是想输出该对象属性的值,我们通过重写toString()方法即可打印对象属性的值:
 


public class People {
    private int age=25;
    private String sex="男";

    @Override
    public String toString() {
        return "People{" +
                "age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    public static void main(String[] args) {
        People people=new People();
        System.out.println(people);

        //输出结果为 People{age=25, sex='男'}
    }
}

2) equals()方法 -》应用场景,当我们想比较两个对象是否相等时,代码如下: 
 

public class People {
    private int age=25;
    private String sex="男";

    @Override
    public String toString() {
        return "People{" +
                "age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    public static void main(String[] args) {
        People people1=new People();
        People people2=new People();
        if(people1.equals(people2)){
            System.out.println("这两个人是同一个人");
        }else{
            System.out.println("这两个人不是同一个人");
        }

        //这两个人不是同一个人
    }
}

我们比较两个对象是否相等时,其实我们想比较的是两个对象的属性值是否相等,这时候我们重写
equals()方法,即可对两个对象进行比较:

public class People {
    private int age=25;
    private String sex="男";

    @Override
    public String toString() {
        return "People{" +
                "age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        People people = (People) o;

        if (age != people.age) return false;
        return sex != null ? sex.equals(people.sex) : people.sex == null;
    }

    @Override
    public int hashCode() {
        int result = age;
        result = 31 * result + (sex != null ? sex.hashCode() : 0);
        return result;
    }

    public static void main(String[] args) {
        People people1=new People();
        People people2=new People();
        if(people1.equals(people2)){
            System.out.println("这两个人是同一个人");
        }else{
            System.out.println("这两个人不是同一个人");
        }

        //结果:这两个人是同一个人
    }
}

2.6 Java中的多态
1.啥子叫多态
即对象的多种形态,分为引用的多态和方法的多态

2.引用的多态
父类的引用可以指向子类的对象 
父类的引用可以指向本类的对象
如:

public class ChinaPeople extends People {

    protected String color="黄棕色";

    public static void main(String[] args) {

        People people=new ChinaPeople();
        People people1=new People();

    }
}

3.方法的多态
创建本类对象时,调用的方法为本类中的方法
创建子类对象时,调用的方法为子类重写的方法或者继承的方法

4.多态中的引用类型转换
1.向上造型(向上类型转换-隐式/自动类型转换),是小类型到大类型的转换
2.向下造型(向下类型转换-强制类型转换),是大类型到小类型的转换

        //向下类型转换-强制转换,存在风险,为什么这样说
        People people1=new People();

        ChinaPeople chinaPeople1=(ChinaPeople) people1;  //向下类型转换-强制转换,存在风险
        
        //编译时没报错,但运行时报错:Exception in thread "main" java.lang.ClassCastException: People cannot be cast to ChinaPeople

3.instanceof 运算符,来解决引用对象的类型,避免类型转换的安全问题
 

 American american=new American();
        People people2=american;  //向上造型-自动转换

        if(people2 instanceof ChinaPeople){
            ChinaPeople chinaPeople2= (ChinaPeople) people2;
        }else{
            System.out.println("people2不是ChinaPeople的实例");
        }

        if(people2 instanceof American){
            System.out.println("people2是American的实例");
            American american1=(American) people2;
        }else{
            System.out.println("people2不是American的实例");
        }

        if(people2 instanceof People){
            System.out.println("people2是People的实例");
            People people3=people2;
        }else{
            System.out.println("people2不是People的实例");
        }


/*输出结果为:
people2不是ChinaPeople的实例
people2是American的实例
people2是People的实例*/

2.7 java中的抽象类

1.什么是抽象类
抽象类前使用abstract关键字修饰,则该类为抽象类

2.抽象类的应用场景
a.在某些情况下,父类只知道其子类应该包含怎样的方法,但无法知道这些子类如何实现这些方法

b.从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类做模板,避免了子类设计的随意性

3.抽象类的作用
限制约定子类必须拥有哪些方法,但不关注实现细节

4.抽象类的使用规则
a.abstract定义抽象类
b.abstract定义抽象方法,只有声明,不需要实现
**c.包含抽象方法的类一定是抽象类
d.抽象类中可以包含普通的方法,也可以没有抽象方法,子类继承抽象类时必须实现抽象类中的抽象方法

abstract public class TelPhone {
    abstract public void call();
    abstract public void sendMessage();
    public void ordinary(){
        System.out.println("抽象类中可以有普通方法");
    }
}

e.抽象类不能直接创建对象,可以定义引用变量指向子类对象
 

2.8 java中的接口

1.接口的概念
接口可以理解为一种特殊的类,由全局常量和公共的抽象方法所组成
接口不关心类的内部数据,也不关心这些类里方法的实现细节,它只规定类里必须提供这些方法

2.接口的定义
常量:
接口中的属性是常量,即使定义时不加上 public static final 修饰符,系统也会自动加上
方法:
接口中的方法只能抽象方法,即使定义时不加上 public abstract 修饰符,系统也会自动加上

3.使用接口
java中的类是单继承的,是不够灵活的,可以通过实现多个接口来做补充-使用关键字Implements

**还有需要注意的一点:
java中的类是单继承的,但是接口是多继承的
接口中方法不能有方法体,同时方法的访问修饰符不能是 private 和 protected

**4.接口配合匿名内部类使用
 

Interface i=new Interface(){
	public void method(){
	system.out.println("匿名内部类实现接口的方式");
	}
};

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值