Java基础

目录

1、什么是面向对象?对面向对象的理解。

2、JDK、JRE、JVM三者区别和联系

3、简述final作用。

4、为什么局部内部类和匿名内部类只能访问局部final变量?

5、String、StringBuffer、StringBuilder区别及使用场景

6、重载和重写的区别

7、接口和抽象类

8、List和Set

9、hashCode和equals

10、ArrayList和LinkedList区别


1、什么是面向对象?对面向对象的理解。

对比面向过程,是两种不同的处理问题的角度

面向过程更注重事情的每一个步骤及顺序,面向对象更注重事情有哪些参与者(对象),以及各自需要做的事。

简单来讲就是,面向过程是一个流程化的步骤,而面向对象是在这件事情中有几个参与者(对象),这几个参与者(对象)分别要干什么,有点分门别类的意思,个人理解为行为动作按照主语进行划分。例如洗衣机洗衣服就有两个对象,一个是人,一个是洗衣机。人的动作是打开洗衣机,放衣服,放洗衣粉,而洗衣机的动作是清洗。

面向对象相对于面向过程,更易于复用、扩展和维护,我个人理解是解耦,使得对象与对象之间的关系没有那么密切,均可以进行单独的修改。

面向对象的三大特性:封装性、继承性、多态性。

封装性:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项。

内部细节对外部调用透明,外部调用无需修改或者关系内部实现(只需要知道如何调用,不需要知道内部如何实现)。

经典的两场景体现:1、属性私有;2、orm框架。

继承性:继承父类的方法,扩展自己的方法。

多态性:基于对象所属类的不同,外部对同一方法的调用,实际执行的逻辑不同。

继承,方法重写,父类引用指向子类对象。(编译看左,运行看右

父类类型 变量名 = new 子类对象;

变量名.方法名();

无法调用子类特有功能。

2、JDK、JRE、JVM三者区别和联系

JDK:Java Development Kit       java开发工具

JRE:Java Runtime Environment        java运行时环境

JVM:Java Virtual Machine        java虚拟机

JDK>JRE>JVM

JDK=JRE+java开发工具(javac java jconsole)

JRE=JVM(虚拟机)+java核心类库

3、简述final作用。

final在java中可以用来修饰类、方法以及变量。

修饰类时,表示类不可被继承

修饰方法时,表示方法不可被子类覆盖(不能重写,但是可以重载

修饰变量:表示变量一旦被赋值就不可以更改它的值。

在修饰变量中,如果修饰普通的成员变量,那么在声明的时候就需要赋值,或者代码块中赋值,或者构造器赋值;

如果修饰的是静态的成员变量(static),在声明时就要赋值,或者静态代码块赋值;

如果修饰的是局部变量,那么在声明时没有初始化不会报错,但在使用之前一定要赋值,且不允许第二次赋值。

如果修饰的是基本数据类型的变量,那么数值一旦初始化之后就不能改变,即final int a = 1;那么后面就不能够再给a进行赋值;

如果修饰的是引用数据类型的变量,那么其初始化后始终只能指向一个对象,但是对象中的变量是可以更改的(即例如有个数组被final修饰,数组中的内容可以更改,但是不能将该数组赋为null

4、为什么局部内部类和匿名内部类只能访问局部final变量?

① 内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就随着方法的执行完毕就被销毁。这是前提条件。

② 于是出现了问题,即当外部类的方法结束时,按照内存回收机制(GC),局部变量就应该被销毁。但是内部类对象可能还存在(只有在不再被引用时才会死亡)。这里就出现了矛盾:内部类对象访问了一个不存在的变量(内部类中有使用到被回收掉的局部变量)。为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的复制,延长了局部变量的生命周期。

③ 在这种情况下,复制的局部变量必须保证与之前的变量一直,因此就将局部变量设置为final,对该局部变量初始化后,就不需要再去修改这个变量,保证了内部类的成员变量和方法局部变量的一致性。

5、String、StringBuffer、StringBuilder区别及使用场景

String在底层源码中是final修饰的,不可变,即每次操作都会产生新的String对象;

StringBuffer和StringBuilder都是在原对象上操作(与String不同);

StringBuffer是线程安全的,StringBuilder是线程不安全的(多线程情况下:1.需不需要额外加锁2.共享变量3.结果不受影响,不会出现并发问题)

StringBuffer的方法都是synchronized修饰的(线程安全的);

性能上:StringBuilder>StringBuffer>String。

在应用场景上,经常需要改变字符串内容时使用StringBuffer和StringBuilder;

优先使用StringBuilder(性能好,但安全性差),多线程使用共享变量时用StringBuffer(线程安全的)。

6、重载和重写的区别

重载:发生在同一个类中方法名必须相同参数类型不同、个数不同、顺序不同,方法返回值和方位修饰符可以不同发生在编译时。(比如在使用idea时,使用一个类中的方法时,会发现同名的方法有很多,但是后面所用的参数类型及个数都不一样)

(注意这个不是重载!!)

重写:发生在子父类中,方法名、参数列表必须相同返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类不能重写该方法。

7、接口和抽象类

① 抽象类可以存在普通成员函数,而接口中只能存在public abstract方法;

② 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

③ 抽象类只能继承一个,接口可以实现多个。

8、List和Set

List:有序,按对象进入的顺序保存对象,可重复允许多个Null元素对象,可以使用Iterator(迭代器)取出所有元素,再逐一遍历,还可以使用get(int index)获取指定下标的元素

Set:无序,不可重复最多允许有一个Null对象,取元素时只能用Iterator接口取得所有元素,再逐一遍历各个元素

9、hashCode和equals

hashCode()的作用是获取哈希码,实际上是返回一个int整。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在JDK的Object.java中,java中的任何类都包含有hashCode()函数。散列表存储的是键值对(key-value),其特点为能根据“键”快速的检索出对应的值。这其中就利用到了哈希码。

以“HashSet如何检查重复”为例说明为什么要有hashCode:

对象加入HashSet时,先计算对象的hashCode判断对象加入的位置,看该位置是否有值,如果没有,HashSet会假设对象没有重复出现。如果该位置发现有值,就调用equals方法检查两个对象是否真的相同。如果相同就不加入,不相同就会重新散列到其他位置。这样的方式减少了equals的次数,提高了执行速度。

如果两个对象相等,则hashCode一定相等

两个对象相等,对两个对象分别调用equals方法都返回true

两个对象有相同的hashCode值,也不一定相等

因此,equals方法被覆盖后,hashCode方法也要覆盖

10、ArrayList和LinkedList区别

ArrayList:基于动态数组连续内存存储适合下标访问

扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组(底层默认扩容1.5倍)。如果不是尾部插入数据还会涉及到元素的移动(往后复制一份后再插入金元素)。使用尾插法并指定初始大小可以极大提升性能、甚至超过LinkedList(需要创建大量node对象)

LinkedList:基于链表存储在分散的内存中,适合做数据插入及删除操作,不适合查询(需要逐一遍历)

遍历LinkedList必须使用Iterator,不要试图使用indexOf等返回元素索引,并利用其遍历。使用indexOf对list进行遍历,当结果为空时会遍历整个列表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值