Java 面试题整理(一)

目录

抽象类和接口的区别

什么时候使用抽象类,什么时候使用接口

八大基本数据类型,所占字节数

List、Set、Map的区别

什么情况下使用List、Map、Set?

ArrayList和LinkedList

​​​​​LinckedList底层

ArrayList底层

Io有哪些流,字节流和字符流的区别

String常用api

自动拆装箱发生

Collections提供的工具方法

String、StringBuffer和StringBuilder区别

Map的键和值可以为null吗,为什么

集合排序,内排序,外排序

动态代理和静态代理

封装、继承、多态

static加载顺序

代理和反射,反射泛型还有用吗

final关键字


抽象类和接口的区别

1. 一个类只能继承一个抽象类,但是可以实现多个接口;

2.  抽象类可以包含具体方法,接口中的所有方法都是抽象的;

3. 抽象类可以声明和使用字段;接口则不能,接口中的变量都是final类型的常量;

4. 抽象类中的方法的修饰符可以是public、protected、private或者default;接口中的方法只能是public(JDK7);

        注意:在JDK8中,Java接口引入了一些新功能 — 默认方法和静态方法;在JDK9中,还可以在接口中使用private私有方法

5. 抽象类可以定义构造函数;接口不能

6. 抽象类主要用来抽象类别,接口主要用来抽象方法功能

        关注事物的本质,用抽象类;关注一种操作,用接口

什么时候使用抽象类,什么时候使用接口

1. 如果想让一部分方法拥有默认实现,使用抽象类。

2. 如果想实现多重继承,必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。

3. 如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。

八大基本数据类型,所占字节数

基本类型

字节数

byte

1

short

2

int

4

long

8

float

4

double

8

char

2

boolean

true/false

List、Set、Map的区别

1. List

      可存储重复对象;

      是一个有序集合,保存了每一个元素的插入顺序,输出顺序就是插入顺序;

      常见的实现类有ArrayList、LinkedList和Vector

2. Set

      不允许重复对象,只允许一个null元素

      无序容器,无法保证每个元素的存储顺序,TreeSet通过Comparator或者Comparable维护了一个排序顺序;

      常见的实现类有HashSet、LinkedHashSet和TreeSet,最流行的是基于HashMap实现的HashSet

3. Map

      Map不是Collection的子接口或者实现类,Map和Collection同级,是一个接口

      以键值对的形式进行数据存储

      键不允许重复,允许null作为Map的键和值 

      TreeMap也通过Comparator或者Comparable维护了一个排序顺序

      常见的实现类有HashMap、TreeMap、LinckedHashMapHashTable

什么情况下使用List、Map、Set?

回答优缺点

1. 经常使用索引对元素进行访问,使用ArrayList,经常对元素进行增加删除操作,使用LinckedList

2. 想让元素按照插入的次序进行有序存储,使用List

3. 想要保证元素的唯一性,使用Set

4. 想要使用键值对的形式进行数据存储,使用Map

ArrayList和LinkedList

1. ArrayList的底层是可变长数组,LinkedList的底层是链表(链表结构特征

2. 经常随机访问数据,ArrayList更快,因为LinkedList要移动指针

3. 经常进行新增和删除操作,LinkedList更快,因为ArrayList要移动数据

​​​​​LinckedList底层

LinkedList底层是一个双向链表,LinkedList的基本操作就是对双向链表的操作。

push()和pop()方法实现

       改变元素的前驱节点和后驱节点的指向

ArrayList底层

可变长数组,初始容量为10,扩容后容量大概为原容量的1.5倍

如何实现自动扩容和缩容:

elementData = Arrays.copyOf(elementData, newCapacity);

总结:

      1. copyOf()的实现是用的是arrayCopy();

      2. arrayCopy()需要目标数组,对两个数组的内容进行可能不完全的合并操作;

      3. copyOf()在内部新建一个数组,调用arrayCopy()将original内容复制到copy中去,并且长度为newLength,返回copy。

Io有哪些流,字节流和字符流的区别

字节流:继承至InputStream、OutputStream,主要用于处理字节或二进制对象

字符流:继承至InputStreamReader、OutputStreamWriter,主要用于处理字符或字符串

区别:

        一个字符对应两个字节,字节流存汉字,会出现乱码

        音频视频歌曲图片:字节流

        文件(中文):字符流

String常用api

方法

用途

charAt()

返回字符串该下标的字符

indexOf()

返回指定字符第一次出现的字符串内的索引

subString()

截取字符串,含头不含尾

valueOf()

将其他类型转换为字符串类型

trim()

去除字符串开头和结尾的空字符

split()

字符串分割

toUpperCase()和toLowerCase()

统一转换为大写或者小写

toString()

转换为String类型

toCharArray()

将字符串转换为字符数组

getBytes()

将字符串转换为字节数组

compareTo()/compareToIngnoreCase()

比较字符串

equals()/equalsIgnoreCase()

比较

concat()

拼接

自动拆装箱发生

int和Integer

JDK 1.5以后

Integer缓存:-128~127

Collections提供的工具方法

sort(),默认情况下是自然排序,还可以设置比较排序

binarySearch(),二分查找

max()/min(),返回集合中最大/最小的元素的角标

reverse(),反转

swap(),将指定List集合中i元素和j元素进行交换

fill(),将集合中所有元素替换成新的元素

copy(),将所有元素从一个列表复制到另外一个列表中

shuffle(),随机置换(排序)

String、StringBuffer和StringBuilder区别

1. 可变与不可变

      String类型的对象是不可变的,任何对String的改变都会引发新的String对象的生成

      StringBuffer和StringBuilder都是可变的

2. 是否多线程安全

      String是不可变的,线程安全

      StringBuffer,对方法加了同步锁,或者对调用的方法加了同步锁,线程安全

      StringBuilder,线程不安全

Map的键和值可以为null吗,为什么

可以

null也是对象,可以作为键值

集合排序,内排序,外排序

常见排序:冒泡、选择、快速、插入、归并、堆

内排序:排序期间数据对象全部存放在内存的排序

外排序:排序期间全部对象太多,不能同时存放在内存中,必须根据排序过程的要求,不断在内,外存间移动的排序

动态代理和静态代理

1. 静态代理

       由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。

2. 动态代理

       代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

      解释JDK动态代理和CGLIB动态代理,aop底层就是动态代理

封装、继承、多态

1. 封装

        通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我 们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程 接口。

2. 继承

        继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

优点

       新的实现很容易,因为大部分是继承而来的

       很容易修改和扩展已有的实现

缺点

       打破了封装,因为基类向子类暴露了实现细节

       白盒重用,因为基类的内部细节通常对子类是可见的

       当父类的实现改变时可能要相应的对子类做出改变

       不能在运行时改变由父类继承来的实现

3. 多态

       多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B 系统有多种提供服务的方式, 但一切对 A 系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写 (override)实现的是运行时的多态性(也称为后绑定)。

        运行时的多态是面向对象最精髓的东西,要实现多态需要做 两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对 象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)

4. 抽象

       抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对 象有哪些属性和行为,并不关注这些行为的细节是什么。

static加载顺序

static可以修饰成员变量、成员方法、代码块、内部类

1. 父类的静态成员变量或者静态代码块

2. 子类的静态成员变量或静态代码块

3. 父类非静态成员变量以及非静态代码块

4. 父类构造方法被加载

5. 子类非静态成员变量以及非静态代码块

6. 子类构造方法被加载

代理和反射,反射泛型还有用吗

编译后泛型就不存在了(泛型擦除),可通过反射来获取泛型信息

final关键字

在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。

1. 修饰变量,被final修饰的变量必须要初始化,赋初值后不能再重新赋值

        这个变量被初始化后便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可变,即不能再指向其他的对象

2. 修饰方法,被final修饰的方法代表不能重写

3. 修饰类,被final修饰的类,不能够被继承

  • 30
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值