Java基础

面向对象与面向过程

面向过程:将问题分解成步骤,根据步骤实现函数,执行时依次调用函数,数据和对数据的操作是分离的
面向对象:将问题分解成对象,描述对象在解决问题的步骤中的行为,对象与属性和行为是关联的
面向过程的优点:性能高,不需要面向对象的实例化;
缺点:代码不易维护,扩展和复用

面向对象的优点:代码易维护、复用和扩展,可以设计出低耦合的系统
缺点:需要实例化对象,性能比面向过程低

JAVA技术体系

  1. java程序设计语言
  2. java虚拟机,JVM
  3. java类库API
  4. CLass文件格式
  5. 来自商业机构和开源社区的第三方类库API

把java程序设计语言、Java虚拟机、Java类库这三部分统称为JDK,是支持java程序开发的最小环境。
把Java类库中的Java SE API子集和java虚拟机两部分成为JRE,是支持java程序运行的标准环境。

在这里插入图片描述

Java与C++的区别

  1. 面向对象语言,java平台无关性
  2. java不提供指针直接访问内存,更安全
  3. java的类是单继承,C++支持多继承,但java的接口可以多继承
  4. java有自动内存管理机制,不需要程序员手动释放内存
  5. c语言中,字符串和字符数组都会有一个额外的字符"\0"表示结束

重载与重写

重载(编译时多态):在同一个类中,方法名相同,但参数不一致,那么可以说,一个方法是另一个方法的重载方法。
参数不一致:参数类型,个数,顺序不同
重写(运行时多态):⼦类继承⾃⽗类的相同⽅法,参数和返回类型和父类的方法保持一致,内部逻辑可以改变。
**注:**如果⽅法的返回类型是void和基本数据类型,则返回值重写时不可修改。但是如果⽅法的返回值是引⽤类型,重写时是可以返回该引⽤类型的⼦类的。
区别:
在这里插入图片描述

Java面向对象编程的三大特性:封装 继承 多态

. java三大特性之一封装

1. 封装的定义?

​ 本质是信息隐藏;就是把对象的属性操作结合成一个独立的整体,并尽可能隐藏对象的内部实现细节,仅保留一些接口允许外界访问内部数据。

2. 为什么需要封装?哪种业务场景里使用到封装?

​ (1)封装消除了传统结构方法中数据与操作分离带来的种种问题,提高了程序的可复用性可维护性(便于修改);

​ (2)通过封装可以实现对数据的访问权限控制,提高了程序的安全性。

3. 如何使用封装?

​ java提供了四种访问权限,通过使用访问控制符修饰数据或者方法来实现封装;

所谓的访问,可以分为两种不同方式:第一,通过对象实例访问;第二,直接访问

​ 如果能直接放问,那一定也可以通过创建对象实例访问。

​ **~public:**公开的访问权限:可以跨包访问;

~default:默认访问权限(不加任何访问控制符):可以同一个包内访问;

~protected:受保护的访问权限,可以被子类访问(跨包也可以);

~private:私有的访问权限,只能在当前类中访问;

. java三大特性之二:继承

1. 继承的定义

​ 继承是从已有的类中派生出新的类,新的类吸收已有类的数据属性和行为,并能扩展新的能力。

2. 为什么需要继承?哪种业务场景里使用到继承?

​ (1)继承是在一般的类基础上进行构造建立扩充新类的最有效手段;

​ (2)继承能够清晰地体现相关类建的层次结构关系,简化人们对事物的认识描述

​ (3)继承复用了基类的数据和方法,减少代码冗余,提升了代码可复用性可维护性

​ (4)处于完全性和可靠性的考虑,java只支持单继承;

3. 如何使用继承?

extends

. java三大特性之三:多态

1. 多态的定义

多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口;
多态类型(英语:polymorphic type)可以将自身所支持的操作套用到其它类型的值上。
抽象一点描述:多态是同一个行为具有多个不同表现形式或形态的能力。从编程的角度上来看,多态一般就是指同一个接口,使用不同的实例而执行不同操作,如图所示
在这里插入图片描述

2. 多态的优势

1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

多态的好处:可以使程序有良好的扩展,并可以对所有多态类的对象进行通用处理,简化代码的编写。

3. 如何使用多态?

继承(多个⼦类对同⼀⽅法的重写)和接⼝(实现接⼝并覆盖接⼝中同⼀⽅法)。
多态存在的三个必要条件
1、继承
2、重写
3、父类(接口类型)引用指向子类(实现类)对象:Parent p = new Child();

String StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的?

String类中使用final关键字修饰字符数组,所以不可变;而StringBuffer 和 StringBuilder没有用final关键字修饰;
String中的对象是不可变的常量,线程安全;StringBuffer对字符串的操作方法加了同步锁,所以是线程安全的;StringBuilder并没有对方法加同步锁,非线程安全。

对于三者使⽤的总结:

  1. 操作少量的数据: 适⽤ String
  2. 单线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuilder
  3. 多线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuffer

自动装箱与拆箱

  • 装箱:将基本类型用它们对应的应用类型包装起来
  • 拆箱:将包装类型转换为基本数据类型

在⼀个静态⽅法内调⽤⼀个非静态成员为什么是非法的?

由于静态⽅法可以不通过对象进⾏调⽤,因此在静态⽅法⾥,不能调⽤其他⾮静态变量,也不可以访问⾮静态变量成员。

static关键字

  1. 修饰变量,这个静态变量不需要依赖于对象来进行访问,只要类被加载就可以通过类名去访问,这个成员会被该类的所有实例对象所共享。
  2. 修饰方法,静态方法也是不需要依赖于对象来进行访问,静态方法中不能调用非静态变量和方法。
  3. 修饰代码块优化程序性能,不能调用非静态变量和方法。

抽象类和接口的区别是什么?

抽象类和接口的联系与区别

抽象类

定义:如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类;抽象类可以构造出一个固定的一组行为的抽象描述,这组行为能够有任意个可能的具体实现方式。
特点

  • 抽象类不能被实例化,子类必须重写父类的所有抽象方法才能实例化,否则就必须声明为抽象类。
  • 抽象类作为一种类的模板,不可修改但支持扩展,是实现面向对象设计原则中开-闭原则(OCP - Open-Closed Principle ) 的关键所在
  • 含有抽象方法的类一定是抽象类,但是抽象类不一定含有抽象方法;

接口

定义:在JAVA编程语言中是一个抽象类型,是抽象方法的集合;
特点

  • 抽象类不能被实例化,实现类必须实现接口内所描述的所有方法才能实例化,否则就必须声明为抽象类。
  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract;
    注:JDK8及以后,允许我们在接口中定义static方法和default方法,并且有方法体;JDK 1.9 以后,允许将方法定义为 private,并且有方法体。使得某些复用的代码不会把方法暴露出去。更多内容可参考 Java 9 私有接口方法
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量。

接口与类的相同与异同

相同点

  • 都不能被初始化,继承类或实现类必须重写或实现所有抽象方法才能初始化,否则必须声明为抽象类。

异同点

  1. 从设计层⾯来说,普通的类是对对象的抽象,抽象类是对类的抽象,是⼀种模板设计,⽽接⼝是对⾏为的抽象,是⼀种⾏为的规范
  2. 抽象类体现的是一种继承关系(继承的优点),父类与派生类本质上是一种事物;而接口体现的是一种功能绑定关系,实现类实现接口方法相当于绑定了某个功能;用门这个例子来说明:
    将门作为抽象概念,包含开门和关门两个动作,可以用抽象类或者接口来定义一个表示该抽象概念的类型;如果现在要求Door还要具有报警的功能,一种解决方案是在门的抽象类或者接口中加入报警方法,但这样违背了接口分离原则ISP(Interface Segregation Priciple),Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。导致接口太胖或者说是接口污染;
    门的开、关门动作与报警器的行为是两种抽象概念,因此需要拆分成两个抽象类型,如果拆分成两个抽象类来定义,显然不行,Java语言不支持多继承;如果拆分成两个接口来定义,原则上可行,但是不够合理。因为报警门在概念本质上还是门,只是具备报警的功能;因此,门的开、关门动作作为基础固有的行为可以用抽象类来定义,而报警功能则用接口来定义。
  3. 接⼝的⽅法默认是 public ,所有⽅法在接⼝中不能有实现(Java 8 开始接⼝⽅法可以有默认实现),⽽抽象类可以有⾮抽象的⽅法。
  4. 接⼝中除了 static 、 final 变量,不能有其他变量,⽽抽象类中则不⼀定。
  5. ⼀个类可以实现多个接⼝,但只能实现⼀个抽象类。接⼝⾃⼰本身可以通过 extends 关键字扩展多个接⼝。
  6. 接⼝⽅法默认修饰符是 public ,抽象⽅法可以有 public 、 protected 和 default 这些修饰符(抽象⽅法就是为了被重写所以不能使⽤ private 关键字修饰!)。

对象的相等与指向他们的引⽤相等,两者有什么不同?

对象的相等,⽐的是内存中存放的内容是否相等。⽽引⽤相等,⽐᫾的是他们指向的内存地址是否相等

== 与 equals(重要)

== : 它的作⽤是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象(基本类型的双等号比较的是值,应用数据类型的双等号比较的是内存地址)
equals:作用是判断两个对象是否是同一个对象,一般有两种情况

  1. 类没有重写equals方法,这时候等价于通过双等号比较两个对象
  2. 类重写了equals方法,一般用来比较两个对象的内容是否相等

hashCode 与 equals (重要)

⾯试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写hashCode ⽅法?

1)hashCode()介绍:

作用是获取哈希码,返回的是一个int整数,哈希码的作用是确定该对象在哈希表中的索引位置。

2)为什么要用hashcode

以HashSet如何检查重复为例子来说明:
每加入一个对象,会先计算hashcode的值来判断对象加入的位置,如果有相符的hashcode,则调用equals方法判断两者是否真的相同,如果相同加入不成功,如果不同,就重新散列到其他位置

3) 为什么重写 equals 时必须重写 hashCode ⽅法?

为了保证:如果两个对象相等,则 hashcode ⼀定也是相同的。两个对象相等,对两个对象分别调⽤ equals⽅法都返回 true。但是,两个对象有相同的 hashcode 值,它们也不⼀定是相等的 。因此,equals ⽅法被覆盖过,则 hashCode ⽅法也必须被覆盖。

4) 为什么两个对象有相同的 hashcode 值,它们也不⼀定是相等的?

因为存储的时候发生碰撞,所谓碰撞也就是指的是不同的对象得到相同的 hashCode 。

ArrayList的扩容机制简述

  1. 初始状态下,容器的大小要么为0要么为自己设定的某个值。
  2. 调用add()方法时,在添加元素到集合中前会先将集合实际元素个数size+1,判定其是否大于数组长度elementDate.length(数组的最大容量,判定是否有数组溢出的风险),如果有则触发扩容机制,扩容机制算法是基于方法grow()的:
  • 先判定数组大小。数组是空或者小于10,那么在扩容的时候将数组直接分配大小到10。
  • 之后的每次扩容,是变成原数组长度的1.5倍:
    • (和实际所需容量、minCapacity相比)如果1.5倍太小的话,则新的容量扩容成实际所需的容量大小(则将实际所需的容量大小(minCapacity)赋值给newCapacity)。
    • (和实际所需容量、minCapacity相比)如果1.5倍太大的话,比较实际所需容量大小与MAX_ARRAY_SIZE的大小,如果大,则新的容量扩容成Integer.MAX_VALUE,否则扩容成MAX_ARRAY_SIZE。

Ps:数组的最大尺寸为2^31 = 2147483648,但是需要8bytes的存储大小表示数组的长度等元数据。所以数组的大小定义为Integer.MAX_VALUE - 8。

数组对象的元数据:

Class:只想描述对象类型的类信息的指针。
Flag:描述对象状态的标志的集合,包括对象的散列码以及对象的形状(即对象是否为数组)。
Lock:对象的同步信息(即对象当前是否同步)。
Size:数组的大小。

HashMap 的⻓度为什么是 2 的幂次⽅

  • HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,实现这个算法就是取模
  • 哈希值对length取余:hash%length,但计算机中直接求余效率不如位运算
  • 优化方案是 用hash&(length-1)来代替hash%length,
  • hash&(length-1) == hash%length 的前提是length是2的n次方;

final修饰局部变量的问题

  • 基本类型:基本类型的值不能发生改变。
  • 引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
    值得注意的是,等号赋值的操作 应用在基本数据类型上相当于是将值改变;而应用在引用数据类型上相当于是将地址改变。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值