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

时间:2021-10-08 23:03:05

更多内容请关注微信公众号【Java技术江湖】

这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!(关注公众号后回复”资料“即可领取 3T 免费技术学习资源以及我我原创的程序员校招指南、Java学习指南等资源)

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

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

三大特性:继承 封装 多态

继承

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

微信公众号【程序员江湖】

作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于2018 年秋招拿到 BAT 头条、网易、滴滴等 8 个大厂 offer

个人擅长领域 :自学编程、技术校园招聘、软件工程考研(关注公众号后回复”资料“即可领取 3T 免费技术学习资源)

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

Java基础1:深入理解Java面向对象三大特性的更多相关文章

  1. Java入门系列(三)面向对象三大特性之封装、继承、多态

    面向对象综述 封装 封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口. 有了封装,就可以明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者:而外部调用者也可以知道 ...

  2. java基础强化——深入理解java注解(附简单ORM功能实现)

    目录 1.什么是注解 2. 注解的结构以及如何在运行时读取注解 2.1 注解的组成 2.2 注解的类层级结构 2.3 如何在运行时获得注解信息 3.几种元注解介绍 3.1 @Retention 3.2 ...

  3. [java基础]一文理解java多线程必备的sychronized关键字,从此不再混淆!

    java并发编程中最长用到的关键字就是synchronized了,这里讲解一下这个关键字的用法和容易混淆的地方. synchronized关键字涉及到锁的概念, 在java中,synchronized ...

  4. 理解PHP面向对象三大特性

    一.封装性 目的:保护类里面的数据,让类更安全, protected和private只能在类中或子类访问,通过public提供有限的接口供外部访问,封装是控制访问,而不是拒绝访问 封装关键字:publ ...

  5. JAVA基础——面向对象三大特性:封装、继承、多态

    JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据. ...

  6. 夯实Java基础系列1:Java面向对象三大特性(基础篇)

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...

  7. Java提高篇之理解java的三大特性——继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  8. 【转】java提高篇&lpar;二&rpar;-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

  9. Java面向对象——三大特性

    Java面向对象——三大特性 摘要:本文主要介绍了面型对象的三大特性. 封装 什么是封装 封装,就是指一个类隐藏了对象的属性和实现细节,对自己的数据和方法进行访问权限控制,只允许某些类和对象进行访问和 ...

  10. &lbrack;&period;net 面向对象编程基础&rsqb; &lpar;11&rpar; 面向对象三大特性——封装

    [.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承. ...

随机推荐

  1. Android自动化测试 - Robotium之re-sign&period;jar重签名后安装失败提示Failure &lbrack;INSTALL&lowbar;PARSE&lowbar;FAILED&lowbar;NO&lowbar;CERTIFICATES&rsqb;解决方案

    问题:在用re-sign.jar重签名apk文件后,显示重签名成功,但在实际安装过程中确提示:Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES] 原因:网上查 ...

  2. Android中的布局动画

    简介 布局动画是给布局的动画,会影响到布局中子对象 使用方法 给布局添加动画效果: 先找到要设置的layout的id,然后创建布局动画,创建一个LayoutAnimationController,并把 ...

  3. Hyper-V 上的android

    为了各种实验环境,装了Hyper-V,然后ADT的android虚拟机就用不上Intel的HAXM了,慢得不行.只有想办法在Hyper-v上装android,还得要ADT能连上. 半天下来,终于搞定. ...

  4. 关于使用rem单位,calc&lpar;&rpar;进行自适应布局

    关于css中的单位 大家都知道在css中的单位,一般都包括有px,%,em等单位,另外css3新增加一个单位rem. 其中px,%等单位平时在传统布局当中使用的比较频繁,大家也比较熟悉,不过px单位在 ...

  5. HW6&period;6

    public class Solution { public static void main(String[] args) { int[] prime = new int[50]; prime[0] ...

  6. &lbrack;Locked&rsqb; Range Sum Query 2D - Mutable

    Range Sum Query 2D - Mutable Given a 2D matrix matrix, find the sum of the elements inside the recta ...

  7. IOC之Unity

    项目最近用到,查找到比较好的资料,记录哈: Unity 3(一):简介与示例: Unity 3(二):Unity在AOP方面的应用

  8. leaflet 利用ajax 将前端地图上的数据post到后台

    生成Google地图,在地图上单击后,将该点的经纬度反馈给后台. 前端HTML代码: <!DOCTYPE html> <html> <head> <meta ...

  9. hdu 1207 汉诺塔II &lpar;DP&plus;递推&rpar;

    汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  10. 富文本 文字图片点击,(TextView)

    textview上的富文本支持 文字,图片的点击事件 - (void)protocolIsSelect:(BOOL)select { NSMutableAttributedString *attrib ...