第3节:Java基础 - 必知必会(上)

本篇是基础篇的第一小节,我们从最基础的java知识点开始学习。本节涉及的知识点包括面向对象的三大特征封装继承多态,并且对常见且容易混淆的重要概念覆盖重载进行比较分析等。本小节主要帮助大家更好的复习与掌握java面试中的基础类题目。

一、面向对象是什么?都有哪些特征?

面向对象是一种思想,可以将复杂问题简单化,让我们从执行者变为指挥者。面向对象的三大特征为:封装继承多态

封装:将事物封装成一个类,减少耦合,隐藏细节。保留特定的接口与外界联系,当接口内部发生改变时,不会影响外部调用方。

继承:从一个已知的类中派生出一个新的类,新类可以拥有已知类的行为和属性,并且可以通过覆盖和重写来增强已知类的能力。

多态:多态的本质就是一个程序中存在多个同名的不同方法,主要通过三种方式来实现:

  • 通过子类对父类的覆盖来实现

  • 通过在一个类中对方法的重载来实现

  • 通过将子类对象作为父类对象使用来实现

解析

这算是一个相当基础的问题,面向对象的思想以及其三大特性我们均需要有较好的理解。接下来,我们对三大特性进行一个详细的阐述与解析吧。

关于封装

封装主要是为了增加程序的可读性,解耦合并且隐藏部分实现细节。让我们来看下边的案例,看看该如何实现封装。

package com.company;

public class Main {

    public static void main(String[] args) {
Student student = new Student();
student.name = "小明";
student.age = 16;
student.printStudentAge(); Student student2 = new Student();
student2.name = "小白";
student2.age = 120;
student2.printStudentAge(); } }
class Student{
String name;
int age; public void printStudentAge(){
System.out.println(name + "同学的年龄:" + age);
}
}

  

程序输出如下:

我们看到小白同学的年龄120,(假设)不符合业务逻辑需要,所以我们需要做一些内部逻辑的处理。所以需要进行代码封装,将内部逻辑进行一个隐藏。

封装之后的代码如下:

package com.company;

public class Main{
public static void main(String[] args) {
Student student = new Student();
student.setName("小明");
student.setAge(16);
student.printStudentAge(); Student student2 = new Student();
student.setName("小白");
student.setAge(120);
student2.printStudentAge();
}
} class Student {
private String name;
private int age; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
if (age < 0 || age > 60) //抛出异常
throw new RuntimeException("年龄设置不合法");
this.age = age;
} public void printStudentAge() {
System.out.println(name + "同学的年龄:" + age);
}
}

  程序输出结果如下:

通过将Student这个类的name和age属性私有化,只有通过公共的get/set方法才能进行访问,在get/set方法中我们可以对内部逻辑进行封装处理,外部的调用方不必关心我们的处理逻辑。

关于继承:

我们需要注意Java中不支持多继承,即一个类只可以有一个父类存在。另外Java中的构造函数是不可以继承的,如果构造函数被private修饰,那么就是不明确的构造函数,该类是不可以被其它类继承的,具体原因我们可以先来看下Java中类的初始化顺序

  • 初始化父类中的静态成员变量和静态代码块

  • 初始化子类中的静态成员变量和静态代码块

  • 初始化父类中的普通成员变量和代码块,再执行父类的构造方法

  • 初始化子类中的普通成员变量和代码块,再执行子类的构造方法

如果父类构造函数是私有(private)的,则初始化子类的时候不可以被执行,所以解释了为什么该类不可以被继承,也就是说其不允许有子类存在。我们知道,子类是由其父类派生产生的,那么子类有哪些特点呢?

  • 子类拥有父类非private的属性和方法

  • 子类可以添加自己的方法和属性,即对父类进行扩展

  • 子类可以重新定义父类的方法,即方法的覆盖/重写

既然子类可以通过方法的覆盖/重写以及方法的重载来重新定义父类的方法,那么我们来看下什么是方法的覆盖/重写吧。(其实这也是一个高频的面试热身题目

覆盖(@Override)

  覆盖也叫重写,是指子类和父类之间方法的一种关系,比如说父类拥有方法A,子类扩展了方法A并且添加了丰富的功能。那么我们就说子类覆盖或者重写了方法A,也就是说子类中的方法与父类中继承的方法有完全相同的返回值类型、方法名、参数个数以及参数类型

Demo展示如下:

package com.company;

public class Main {
public static void main(String[] args) {
new Son().say();
}
}
class Parent {
public void say(){
System.out.println("我是父类中的say方法");
}
}
class Son extends Parent {
@Override
public void say(){
System.out.println("我是子类中的say方法,我覆盖了父类的方法");
}
}

  

我们可以看到,子类本身继承了父类的say方法,但是其想重新定义该方法的逻辑,所以就进行了覆盖。

关于多态:

通过方法的覆盖和重载可以实现多态,上边我们介绍了何为方法的覆盖,这里我们先来介绍下何为方法的重载:

重载:

重载是指在一个类中(包括父类)存在多个同名的不同方法,这些方法的参数个数,顺序以及类型不同均可以构成方法的重载。如果仅仅是修饰符、返回值、抛出的异常不同,那么这是2个相同的方法。

Demo展示如下:

package com.company;

public class Main {

    public void method1(String name, int age){
System.out.println("");
}
// 两个方法的参数顺序不同,可以构成方法的重载
public void method1(int age, String name){
System.out.println("");
}
//---------------------------------------------
public void method2(String name){
System.out.println("");
}
// 两个方法的参数类型不同,可以构成方法的重载
public void method2(int age){
System.out.println("");
} //---------------------------------------------
public void method3(String name){
System.out.println("");
}
// 两个方法的参数个数不同,可以构成方法的重载
public void method3(int age, int num){
System.out.println("");
}
}

  

在这里需要注意如下面试官的追问问题(高频)。

如果只有方法返回值不同,可以构成重载吗?

答:不可以。因为我们调用某个方法,有时候并不关心其返回值,这个时候编译器根据方法名和参数无法确定我们调用的是哪个方法。

举例:如果我们分别定义了如下的两个方法:

public String Test(String userName){ }
public void Test(String userName){ }

  

在调用的时候,直接 Test(“XiaoMing”); 那么就会存在歧义。

我们再来看看如何通过将子类对象作为父类对象使用来实现多态。

把不同的子类对象都当作父类对象来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。这样操作之后,父类的对象就可以根据当前赋值给它的子类对象的特性以不同的方式运作。

对象的引用型变量具有多态性,因为一个引用型变量可以指向不同形式的对象,即:子类的对象作为父类的对象来使用。在这里涉及到了向上转型和向下转型,我们分别介绍如下:

向上转型:子类对象转为父类,父类可以是接口。公式:Father f = new Son(); Father是父类或接口,Son是子类。

向下转型:父类对象转为子类。公式:Son s = (Son) f;

在向上转型的时候我们可以直接转,但是在向下转型的时候我们必须强制类型转换。并且,如案例中所述,该父类必须实际指向了一个子类对象才可强制类型向下转型,即其是以这种方式Father f = new Son()创建的父类对象。若以Father f = new Father()这种方式创建的父类对象,那么不可以转换向下转换为子类的Son对象,运行会报错,因为其本质还是一个Father对象。

本题总结:

在本题目中,我们较为详细的解释了面向对象的三大特性封装,继承与多态。另外对常见面试考察点覆盖和重载也做出了区别与解释。由于重写(覆盖)与重载在名字上容易混淆,所以重写(覆盖)与重载的区别是面试中的高频考点,希望大家可以从原理上来理解与记忆。

(2)JDK,JRE和JVM的区别与联系有哪些?

三者的基本概念可以概括如下:

  • JDK(Java Development Kit)是一个开发工具包,是Java开发环境的核心组件,并且提供编译、调试和运行一个Java程序所需要的所有工具,可执行文件和二进制文件,是一个平台特定的软件

  • JRE(Java Runtime Environment)是指Java运行时环境,是JVM的实现,提供了运行Java程序的平台。JRE包含了JVM,但是不包含Java编译器/调试器之类的开发工具

  • JVM(Java Virtual Machine)是指Java虚拟机,当我们运行一个程序时,JVM负责将字节码转换为特定机器代码,JVM提供了内存管理/垃圾回收和安全机制等

区别与联系:

  • JDK是开发工具包,用来开发Java程序,而JRE是Java的运行时环境

  • JDK和JRE中都包含了JVM

  • JVM是Java编程的核心,独立于硬件和操作系统,具有平台无关性,而这也是Java程序可以一次编写,多处执行的原因

解析:

这也是一道Java的基础题,因为我们学习Java都是从安装一个JDK开始的。上边有说Java程序具有平台无关性,可以做到一次编写,多处执行。那么Java的跨平台性是如何实现的呢?

我们知道,Java程序都是运行在Java虚拟机,即JVM之上。JVM屏蔽了底层操作系统和硬件的差异。我想大多数同学的Hello Word程序都是在文本文件中写的,然后我们通过javac来编译.java文件,生成了一个.class文件,最后再通过java命令来运行.class文件。其实这就是经历了一个先编译,再解释执行的过程,即先将java文件编译成了字节码.class文件,然后交给Java虚拟机解释成特定平台上的机器码

另外一个与平台无关性的原因是,Java的语言规范中规定了基本数据类型的取值范围和行为在各个平台上是保持一致的。

我们做一个简单的总结:

Java语言的平台无关性是如何实现的?

  • JVM屏蔽了操作系统和底层硬件的差异

  • Java面向JVM编程,先编译生成字节码文件,然后交给JVM解释成机器码执行

  • 通过规定基本数据类型的取值范围和行为

Java语言是编译型还是解释型语言?

答:Java的执行经历了编译和解释的过程,是一种先编译,后解释执行的语言,不可以单纯归到编译性或者解释性语言的类别中。

总结:

本小节是Java基础篇章的第一小节,本节中所述知识点均为面试的热身题目,熟练掌握这些题目,可以留下扎实的基础.

第3节:Java基础 - 必知必会(上)的更多相关文章

  1. 第5节:Java基础 - 必知必会(下)

    第5节:Java基础 - 必知必会(下) 本小节是Java基础篇章的第三小节,主要讲述Java中的Exception与Error,JIT编译器以及值传递与引用传递的知识点. 一.Java中的Excep ...

  2. 第4节:Java基础 - 必知必会(中)

    第4节:Java基础 - 必知必会(中) 本小节是Java基础篇章的第二小节,主要讲述抽象类与接口的区别,注解以及反射等知识点. 一.抽象类和接口有什么区别 抽象类和接口的主要区别可以总结如下: 抽象 ...

  3. Java面试必知必会(扩展)——Java基础

    float f=3.4;是否正确? 不正确 3.4是双精度,将双精度赋值给浮点型属于向下转型,会造成精度损失: 因此需要强制类型转换: 方式一:float f=(float)3.4 方式二:float ...

  4. Java面试必知必会:基础

    面试考察的知识点多而杂,要完全掌握需要花费大量的时间和精力.但是面试中经常被问到的知识点却没有多少,你完全可以用 20% 的时间去掌握 80% 常问的知识点. 一.基础 包括: 杂七杂八 面向对象 数 ...

  5. 迈向高阶:优秀Android程序员必知必会的网络基础

    1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...

  6. 【SQL必知必会笔记(1)】数据库基础、SQL、MySQL8.0.16下数据库、表的创建及数据插入

    文章目录 1.数据库基础 1.1 数据库(database) 1.2 表(table) 1.3 列和数据类型 1.4 行 1.5 主键 2.什么是SQL 3.创建后续练习所需数据库.表(MySQL8. ...

  7. Java并发必知必会第三弹:用积木讲解ABA原理

    Java并发必知必会第三弹:用积木讲解ABA原理 可落地的 Spring Cloud项目:PassJava 本篇主要内容如下 一.背景 上一节我们讲了程序员深夜惨遭老婆鄙视,原因竟是CAS原理太简单? ...

  8. 必知必会之 Java

    必知必会之 Java 目录 不定期更新中-- 基础知识 数据计量单位 面向对象三大特性 基础数据类型 注释格式 访问修饰符 运算符 算数运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 三目表达式 ...

  9. .NET零基础入门09:SQL必知必会

    一:前言 仿佛到了更进一步的时候了,每一个程序员迟早都会遇到数据存储的问题.我们拿什么来存储程序产生的数据?举例来说,用什么来存储我们的打老鼠游戏每次的成绩呢?选择如下: 1:内存中.缺点,退出游戏, ...

随机推荐

  1. C语言:互质

    今天遇到一道奇怪的程序题,和平常的不同.同样都是互质,但是一般的题目都是判断两个数字是否互质,但这道题则是给定一个数字n,要求输出所有小于等于n的与n互质的数,题目已经在下面给出: 质数与互质概念不是 ...

  2. Python 基础 三 反射

    Python 基础 三 反射 今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己.在我们Python的面向对象中的反射是啥意思呢?就是通过字符串的形式操作对象相关的属性.python中的一 ...

  3. Servlet相关学习

    Servlet入门解析 概念 运行在服务器端的小程序 servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则 实现servlet接口.复写方法 快速入门 创建web项目 ...

  4. js 把数组中每个元素的某个字段取出

    方法一:map() let cities = [ {city:"北京",bOn:false}, {city:"上海",bOn:false}, {city:&qu ...

  5. nyoj 739 笨蛋难题四

    笨蛋难题四 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 这些日子笨蛋一直研究股票,经过调研,终于发现xxx公司股票规律,更可喜的是 笨蛋推算出这家公司每天的股价, ...

  6. vim-plug golang定义跳转godef

    go get -v github.com/rogpeppe/godef go install -v github.com/rogpeppe/godef ~/.config/nvim/init.vim ...

  7. DNS简单配置

    ——主要执行的程序:/usr/sbin/named ——系统服务:named ——默认端口:53 ——运行时的虚拟根环境:/var/named/chroot ——主配置文件:/etc/named.co ...

  8. elementui 模态框 拖动

    第一步引入import elDragDialog from "@/directive/el-dragDialog";第二步 在export default中声明directives ...

  9. java中大整型BigInteger及setBit和testBit方法

    最近在修改公司之前的项目,在项目中遇到了权限校验的问题,代码中出现了BigInteger的setBit()testBit()方法,之前未接触过,所以了解了下BigInteger. 在Java中,由CP ...

  10. WebGL简易教程(十三):帧缓存对象(离屏渲染)

    目录 1. 概述 2. 示例 2.1. 着色器部分 2.2. 初始化/准备工作 2.2.1. 着色器切换 2.2.2. 帧缓冲区 2.3. 绘制函数 2.3.1. 初始化顶点数组 2.3.2. 传递非 ...