【JavaSE】12-OOP 面向对象编程[OOP特性、接口、内部类]

这篇博客深入探讨了面向对象编程的三大特性——封装、继承和多态,详细解释了如何实现数据的隐藏、方法的重写以及super关键字的使用。此外,还介绍了内部类的概念,包括成员内部类、静态内部类、局部内部类和匿名内部类的应用。同时,讨论了抽象类和接口的区别,以及如何利用instanceof关键字进行类型检查和转换。
摘要由CSDN通过智能技术生成

①.面向对象的三大特性

-封装

要求:“该露的露,该藏的藏”
程序要求“高内聚,低耦合”。
-高内聚就是类内部数据的操作细节自己完成,不允许外部干涉;
-低耦合就是仅暴露少量的方法供外部调用。
封装(数据的隐藏):通常,应该禁止直接访问对象中数据的实际表示,而应通过接口来访问,这称为信息的隐藏。
“属性私有,get / set”

public class Student {
    //属性私有
    private String name;    //名字
    private int id;    //学号
    private char sex;    //性别
    private int age;     //年龄
    //使用private关键字修饰后,这些属性就不能直接被外部调用了
    //'name' has private access in 'com.oop.oppfeature.Student'
    //如果需要修改这些属性,就需要提供一些方法
    //需要设置一些public的get与set方法

    //get获得这个数据
    public String getName(){
        return name;
    }

    //set设置这个数据
    public void setName(String name){
        this.name = name;
    }
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }

    public char getSex() {
        return sex;
    }
    
    public void setSex(char sex) {
        if (sex == '男' || sex == '女'){
            this.sex = sex;
        }else{
            System.out.println("非法输入!");
        }
    }

    public static void main(String[] args) {
        Student s1 =new Student();
        s1.setSex('1');  //输出:非法输入!
    }
}
  • 封装的好处:
    可以提高程序的安全性,保护数据
    隐藏代码的实现细节
    统一接口
    增加系统的可维护行
  • 生成JavaBean快捷键
    Alt + Shift + insert —> getter and setter
    右键—>Generator —> getter and setter

-继承

本质:是对某一批类的抽象,从而实现对世界的更好的建模。
extends的意思是“扩展”,子类,是父类的扩展。
Java中只有单继承,没有多继承

继承是类与类的一种关系。除此之外,类和类之间还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用extends关键字来声明

//人 是一个大的概念,也是对类的抽象
public class Person {
    //public
    //protected
    //default
    //private  属性修饰符优先级

    //父类自己的属性应该私有,需要修改调用应该设置get set接口
    private double money = 10000000;
    //Ctrl + H 查看继承树

    public void say(){
        System.out.println("说了一句话");
    }

	public static void main(String[] args) {
        Student student = new Student();
        student.say();  //是Person类中的方法,子类继承父类的所有非私有方法

        //在Java中所有的类都直接或间接继承Object类
        Person person = new Person();
        person.hashCode();
    }
}

子类会继承父类的所有public方法
Java中所有的类都直接或者间接的继承Object类

·super详解

super的作用:可以调用父类中的非私有方法,可以调用父类的构造器。
super注意点:

  • super()调用父类的构造方法,必须在子类构造方法的第一句
  • super只能出现在子类的方法中,super()只能出现在子类的构造方法中
  • super与this不能同时调用构造方法

super 与 this的区别

  • 代表对象不同:
    this:本来的调用者这个对象
    super:代表父类的引用
  • 前提不同:
    this:在非继承状态也能使用
    super:只能在继承状态下使用
  • 构造方法不同:
    this:调用本类构造
    super:调用父类构造

·方法的重写

方法重写的规则:需要有继承关系,子类重写父类的方法

  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符范围可以扩大,但是不能缩小
    public - protected - default - private
  • 抛出的异常:范围可以被缩小,但不能扩大:ClassNotFoundException - Exception(大)

子类的方法必须和父类一致,但是方法体不同!
为什么需要重写?

  • 子类不一定需要,不一定满足于父类的功能
    Alt + insert —> override

注意方法的重写和方法的重载的区别
方法重载的规则:

  • 方法名称必须相同
  • 形参列表必须不同(个数不同 / 类型不同 / 参数排列顺序不同等)
  • 方法的返回值类型可以相同,也可以不相同。
  • 仅仅返回值类型不同是不足以构成方法的重载的。

-多态

可以实现动态编译:提升类型的可扩展性
同一个方法可以根据发送对象的不同而采取多种不同的处理方式。
一个对象的实际类型是确定的,但可以指向的引用的类型有很多。

多态存在的条件:

  • 有继承关系,父类子类之间有联系才能建立多态
    否则会造成类型转换异常 ClassCastException!
  • 子类重写了父类的方法
  • 父类的引用对象指向子类 Father f1 = new Son();

多态注意:

  • 多态是针对方法来说的,属性没有多态
  • 不能重写的方法
    static 方法,从属于类不属于实例
    final 常量
    private 方法,私有方法

·instanceof 关键字与类型转换

instanceof 判断两个对象的从属关系

public static void main(String[] args) {

        //Object --> Person --> Student
        //                  --> Teacher
        Object object = new Student();

        System.out.println(object instanceof Student);  //true
        System.out.println(object instanceof Person);   //true
        System.out.println(object instanceof Object);   //true
        System.out.println(object instanceof Teacher);  //false
        System.out.println(object instanceof String);   //false

        System.out.println("===================================");
        Person person = new Student();
        System.out.println(person instanceof Student);  //true
        System.out.println(person instanceof Person);   //true
        System.out.println(person instanceof Object);   //true
        System.out.println(person instanceof Teacher);  //false
        // System.out.println(person instanceof String);   //编译报错!

        System.out.println("===================================");
        Student student = new Student();
        System.out.println(student instanceof Student);  //true
        System.out.println(student instanceof Person);   //true
        System.out.println(student instanceof Object);   //true
        //Inconvertible types;
        //System.out.println(student instanceof Teacher);  //编译报错! 同级比较
        // System.out.println(person instanceof String);   //编译报错! 同级比较

        //System.out.println(X instanceof Y);   //能不能编译通过主要看X指向的类型是否是Y的子类型

    }
}

类型转换
把子类转化为父类,向上转型,不用强制转换 可能会丢失方法
把父类转化为子类,向下转型,需要强制转化 可能丢失精度
意义:不用new一个新的类,通过类型的转化就可以调用不同的类型的方法,提高代码利用率。

//Person为Student父类,go为Student中的方法
public static void main(String[] args) {
        //类型之间的转化:基本类型转化 高>低 64 -> 16 -> 8 ...
        //            父类 -> 子类
        //高                    低
        Person p1 = new Student();
        //将student对象转换为Student类型,就可以使用Student类型的方法了
        Student stu = (Student) p1;
        //可以使用student类型的方法了
        stu.go();
        //子类转换为父类有可能丢失自己本来的一些方法
        Student student = new Student();
    }

·static关键字

  • 静态属性(变量),从属于类,public static int age;
    可以直接被类所使用Student.age; 不用通过new对象就能访问
  • 静态代码块,从属于类,在类加载的时候就会被一起加载,并且只会加载一次。
  • 静态的方法,和类一起加载的,不能被继承的。
  • 静态的导入包 import static java.lang.Math.PI;
    可直接在之后的语句中直接使用 double d2 = PI;
import static java.lang.Math.random;

//static:
public class Student {
    private static int age;             //静态变量  多线程
    private double score = random();    //非静态变量
    public void run(){}
    public static void go(){
        System.out.println("go to");
    }
    {
        System.out.println("执行匿名代码块");
    }
    static{
        System.out.println("执行静态代码块");
    }
    public Student() {
        System.out.println("执行构造器");
    }

    public static void main(String[] args) {
        Student student = new Student();
        /*
            执行静态代码块     只执行一次,再次新建对象不再执行
            执行匿名代码块     随着对象的新建会被再次执行
            执行构造器        新建对象也将会执行构造器
         */
        System.out.println(Student.age);
        // System.out.println(Student.score);
        // 报错:Non-static field 'score' cannot be referenced from a static context
    }
}

②.抽象类和接口

-抽象类

abstract修饰符可以用来修饰方法也可以用来修饰类
如果用来修饰方法,那这个方法就是抽象方法
如果用来修饰类,那么该类就是抽象类。
抽象类不能用new关键字来创建对象,它是用来让子类继承的
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
注意:子类如果继承抽象类,那么必须实现抽象类没有实现的抽象方法,否则该子类也需要声明为抽象类。

//abstract 抽象类
public abstract class Action {

    //约束,要求别人帮我们实现
    //abstract,抽象方法,只有方法的名字,没有方法的实现!
    public abstract void doSomeThing();

    //1.不能new这一个抽象类,只能靠子类去实现它:约束!
    //2.抽象类当中也以写普通方法,但是抽象方法必须要在抽象类当中
    //3.抽象类存在的意义:将多个类的共同特点抽象出来,再重新写某一个类的时候,提高现有代码的使用效率
}
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非该类也是抽象类
//extends 有局限性,Java只能单继承  但是接口解决了这个问题,接口可以多继承
public class AType extends Action{
    @Override
    public void doSomeThing() {

    }
}

-接口

普通类:只有具体的实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范!自己无法写方法,专业的约束!约束和实现分离:面向接口编程。

接口就是规范,定义的是一组具体的规则,体现了在现实中“如果你是…则必须能…”的思想
接口的本质就是契约,如同法律,一旦制定,那大家都必须要遵守。
面向对象-OO 的精髓,是对 对象 的抽象。
关键字:interface
注意:

  • 接口中定义的方法都是抽象的默认为public abstract 抽象方法
  • 接口中定义的所有量都是默认public static final 常量
//interface关键字可以定义接口,接口都需要相应的实现类
public interface UserService {
    //接口中的所有定义的方法都是抽象的 默认 public abstract
    public abstract void run(String a);
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);

    //接口当中定义的量都是常量
    public static final int AGE = 99;
    String NAME = "iFinder";
}
public interface TimeService {
    void timer();
}

接口的实现

  • 一个类可以通过implements实现接口
  • 通过逗号分隔,可同时实现多个接口
  • 实现了接口的类,必须重写接口的方法
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void run(String a) {
    }

    @Override
    public void add(String name) {
    }

    @Override
    public void delete(String name) {
    }

    @Override
    public void update(String name) {
    }

    @Override
    public void query(String name) {
    }

    @Override
    public void timer() {
    }
}

③.内部类

-内部类

  • 定义:内部类就是在一个类的内部再定义一个类。
    比如,A类的内部定义一个B类,那么B类就是A类的一个内部类,A类就是B类的外部类。
  • 分类:
    成员内部类
    静态内部类
    局部内部类
    匿名内部类

成员内部类:
在类的内部定义,可以获得外部类的一些私有的属性。
通过外部类的实例变量来新建内部类对象。

public class Outer {

    private int id = 144000;

    public void out(){
        System.out.println("这是外部类的方法");
    }

    public class Inner{
        public void in(){
            System.out.println("这是内部类");
        }

        //内部类可以获得外部类的私有属性
        public void getId(){
            System.out.println(id);
        }
    }
}
public static void main(String[] args) {
        //new关键字,新建一个外部类
        Outer outer = new Outer();

        //通过外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();    //输出:这是内部类
        inner.getId(); //输出:144000
    }

匿名内部类:
没有名字的初始化类,不用保存到变量当中

public class NoName {
    public static void main(String[] args) {
        //匿名内部类,没有名字的初始化类,不用保存到变量中
        new Apple().eat();
    }
}

class Apple{
    public void eat(){
        System.out.println("1");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值