Java基础1:深入理解Java面向对象三大特性

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/80048732 这位大侠,这是我的公众号:程序员江湖。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/80048732


微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。(关注公众号后回复”Java“即可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源。

本文主要介绍了final关键字的使用方法及原理

本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理。

具体代码在我的GitHub中可以找到:

https://github.com/h2pl/MyTech

文章首发于我的个人博客:

https://h2pl.github.io/2018/04/22/javase1/

三大特性:继承 封装 多态

继承

Java中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承。

public class Son extends Father{
public void go () {
System.out.println("son go");
}
public void eat () {
System.out.println("son eat");
}
public void sleep() {
System.out.println("zzzzzz");
}
public void cook() {
//匿名内部类实现的多继承
new Mother().cook();
//内部类继承第二个父类来实现多继承
Mom mom = new Mom();
mom.cook();
}
private class Mom extends Mother {
@Override
public void cook() {
System.out.println("mom cook");
}
}
}

封装

封装主要是因为Java有访问权限的控制。public > protected > package = default > private。封装可以保护类中的信息,只提供想要被外界访问的信息。

类的访问范围

A、public    包内、包外,所有类中可见
B、protected 包内所有类可见,包外有继承关系的子类可见
(子类对象可调用)
C、(default)表示默认,不仅本类访问,而且是同包可。
D、private   仅在同一类中可见 

多态

多态一般可以分为两种,一个是重写overwrite,一个是重载override。

重写是由于继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。重载是因为一个同名方法可以传入多个参数组合。

注意,同名方法如果参数相同,即使返回值不同也是不能同时存在的,编译会出错。

从jvm实现的角度来看,重写又叫运行时多态,编译时看不出子类调用的是哪个方法,但是运行时操作数栈会先根据子类的引用去子类的类信息中查找方法,找不到的话再到父类的类信息中查找方法。
    而重载则是编译时多态,因为编译期就可以确定传入的参数组合,决定调用的具体方法是哪一个了。

向上转型和向下转型的解释 :

public static void main(String[] args) {
        Son son = new Son();
        //首先先明确一点,转型指的是左侧引用的改变。
        //father引用类型是Father,指向Son实例,就是向上转型,既可以使用子类的方法,也可以使用父类的方法。
        //向上转型,此时运行father的方法
        Father father = son;
        father.smoke();
        //不能使用子类独有的方法。
        // father.play();编译会报错
        father.drive();
        //Son类型的引用指向Father的实例,所以是向下转型,不能使用子类非重写的方法,可以使用父类的方法。
        //向下转型,此时运行了son的方法
        Son son1 = (Son) father;
        //转型后就是一个正常的Son实例
        son1.play();
        son1.drive();
        son1.smoke();
        ```
        //因为向下转型之前必须先经历向上转型。

        //        在向下转型过程中,分为两种情况:
        //
        //        情况一:如果父类引用的对象如果引用的是指向的子类对象,
        //        那么在向下转型的过程中是安全的。也就是编译是不会出错误的。
            //因为运行期Son实例确实有这些方法
            Father f1 = new Son();
            Son s1 = (Son) f1;
            s1.smoke();
            s1.drive();
            s1.play();
        //        情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,
        //        但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。
        //因为运行期Father实例并没有这些方法。
            Father f2 = new Father();
            Son s2 = (Son) f2;
            s2.drive();
            s2.smoke();
            s2.play();
        //向下转型和向上转型的应用,有些人觉得这个操作没意义,其实可以用于方法参数中的类型聚合,然后具体操作再进行分解。
        //比如add方法用List引用类型作为参数传入,传入具体类时经历了向下转型
        add(new LinkedList());
        add(new ArrayList());

        //总结
        //向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法
        //并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错。
        //若安全则继续执行方法。

    }
    public static void add(List list) {
        System.out.println(list);
        //在操作具体集合时又经历了向上转型
//        ArrayList arr = (ArrayList) list;
//        LinkedList link = (LinkedList) list;
    }

总结:
向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法。并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错,若安全则继续执行方法。

编译期的静态分派:其实就是根据引用类型来调用对应方法。

public static void main(String[] args) {
    Father father  = new Son();
    静态分派 a= new 静态分派();

    //编译期确定引用类型为Father。
    //所以调用的是第一个方法。
    a.play(father);
    //向下转型后,引用类型为Son,此时调用第二个方法。
    //所以,编译期只确定了引用,运行期再进行实例化。
    a.play((Son)father);
    //当没有Son引用类型的方法时,会自动向上转型调用第一个方法。
    a.smoke(father);
    //


}
public void smoke(Father father) {
    System.out.println("father smoke");
}
public void play (Father father) {
    System.out.println("father");
    //father.drive();
}
public void play (Son son) {
    System.out.println("son");
    //son.drive();
}

方法重载优先级匹配

public static void main(String[] args) {
        方法重载优先级匹配 a = new 方法重载优先级匹配();
        //普通的重载一般就是同名方法不同参数。
        //这里我们来讨论当同名方法只有一个参数时的情况。
        //此时会调用char参数的方法。
        //当没有char参数的方法。会调用int类型的方法,如果没有int就调用long
        //即存在一个调用顺序char -> int -> long ->double -> ..。
        //当没有基本类型对应的方法时,先自动装箱,调用包装类方法。
        //如果没有包装类方法,则调用包装类实现的接口的方法。
        //最后再调用持有多个参数的char...方法。
        a.eat('a');
        a.eat('a','c','b');
    }
    public void eat(short i) {
        System.out.println("short");
    }
    public void eat(int i) {
        System.out.println("int");
    }
    public void eat(double i) {
        System.out.println("double");
    }
    public void eat(long i) {
        System.out.println("long");
    }
    public void eat(Character c) {
        System.out.println("Character");
    }
    public void eat(Comparable c) {
        System.out.println("Comparable");
    }
    public void eat(char ... c) {
        System.out.println(Arrays.toString(c));
        System.out.println("...");
    }

//    public void eat(char i) {
//        System.out.println("char");
//    }

下一节具体介绍了基本数据类型以及常量池,具体请见:

https://blog.csdn.net/a724888/article/details/80041698

相关文章
|
1天前
|
安全 Java 大数据
探索Java的奇妙世界:语言特性与实际应用
探索Java的奇妙世界:语言特性与实际应用
|
1天前
|
安全 Java
Java基础&面向对象&继承&抽象类
Java基础&面向对象&继承&抽象类
|
1天前
|
Java
【Java基础】详解面向对象特性(诸如继承、重载、重写等等)
【Java基础】详解面向对象特性(诸如继承、重载、重写等等)
5 0
|
1天前
|
Java
[Java 基础] Java修饰符
[Java 基础] Java修饰符
|
6天前
|
安全 Java 机器人
《Java 简易速速上手小册》第2章:面向对象的 Java(2024 最新版)
《Java 简易速速上手小册》第2章:面向对象的 Java(2024 最新版)
19 0
|
7天前
|
机器学习/深度学习 Java API
Java8中的新特性
Java8中的新特性
|
10天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。
|
10天前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【4月更文挑战第16天】本文将介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁、易读。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而使代码更加简洁、高效。本文将通过实例代码详细讲解这两个新特性的使用方法和优势。
|
11天前
|
Java 索引
Java基础教程(6)-Java中的流程控制语句
【4月更文挑战第6天】Java流程控制包括选择(if, switch)、重复(while, do-while, for)和跳转(break, continue, return)语句。选择语句根据条件执行不同路径,if和switch用于单条件和多条件分支。重复语句用于循环,如for循环的初始化、条件和迭代部分,以及while和do-while循环。跳转语句中,break用于立即退出循环,continue结束当前循环迭代,return则从方法中返回。此外,Java的for each循环简化了数组或集合的遍历,但不能控制遍历顺序或索引。
|
13天前
|
存储 Java 编译器
Java基础教程(4)-Java中的操作符
【4月更文挑战第4天】Java中的String是常用类,字符串是不可变对象,用双引号表示。String对象在编译期长度受限于65535,运行期不超过Int范围。字符串方法如length()、substring()、replace()、equals()等提供了多种操作。可变字符串可使用StringBuffer或StringBuilder。String对象通过字符串池优化内存,池中已有相同内容字符串则返回其引用。