java面试题一

这篇博客详细探讨了Java编程中的核心概念——面向对象的三大特征:封装、继承和多态,以及内存管理机制,包括堆、栈和方法区的运作。文章解释了如何通过访问控制修饰符实现封装,通过单一继承和多接口实现实现继承,以及如何利用多态提高代码的灵活性。同时,还介绍了JVM的垃圾回收机制,强调了内存泄漏的危害以及如何避免。此外,讨论了Java中的接口、抽象类、多态的应用,以及内存区域的管理,包括堆、栈和方法区的作用和生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向对象三大特征:

1)封装:

1.1)类:封装的是对象的属性和行为

1.2)方法:封装的是特定业务功能实现

1.3)访问控制修饰符:封装访问的权限

2)继承:

2.1)作用:代码的复用,减少代码的重复

2.2)超类:所有派生类所共有的属性和行为

接口:部分派生类所共有的行为

派生类:派生类所特有的属性和行为

2.3)单一继承、多接口实现

传递性

3)多态:

3.1)意义:行为的多态、对象的多态

3.2)向上造型、强制类型转换、instanceof

3.3)多态的表现形式:

3.3.1)重写:根据对象来实现多态

3.3.2)重载:根据参数来实现多态

 

 

1.内存管理:由JVM来管理

1)堆:

1.1)存储所有new出来的对象(包括实例变量)

1.2)垃圾:没有任何引用所指向的对象

垃圾回收器(GC)不定时到内存中去清扫垃圾

回收过程是透明的(看不到的),并不一定一发现

垃圾就立刻回收,可以调用System.gc()建议

虚拟机尽快调度GC来进行回收

1.3)内存泄漏:不再使用的内存还没有被及时的回收

严重的泄漏会导致系统的崩溃

建议:不再使用的对象及时将引用设置为null

1.4)实例变量的生命周期:

创建对象时存储在堆中,对象被回收时一并被回收

2)栈:

2.1)存储正在调用的方法中的所有局部变量(包括方法的参数)

2.2)在调用方法时为在栈中为该方法分配一块对应的栈帧,

栈帧中存储方法的局部变量以及方法的参数

当方法调用结束时,栈帧被清除,局部变量一并失效

2.3)局部变量的生命周期:

调用方法时存在栈中,方法结束时与栈帧一并被清除

3)方法区:

3.1)存储.class字节码文件(包括方法、静态变量)

3.2)方法只有一份,通过this来区分具体的对象

 

 

1.接口:

是一种数据类型(引用类型)

由interface定义,只能包含常量和抽象方法

不能被实例化,是需要被实现的,实现类:

必须重写接口中的所有抽象方法

一个类可以实现多个接口,用逗号分隔

若又继承又实现时,应先继承后实现

接口可以继承接口

接口只可以被public 和 abstract 修饰

2.多态:

1)意义:行为多态(抽象方法都是多态的)

对象多态(向上造型的对象都是多态的)

2)向上造型(自动类型转换):

超类型引用指向派生类的对象

能点出来什么,看引用的类型

能造型成: 超类+所实现的接口

3)强制类型转换,成功的条件只有如下两种:

3.1)引用所指向的对象,就是该类型

3.2)引用所指向的对象,实现了该接口

4)若不符合如上两个条件,则发生ClassCastException类型转换异常

建议:在强制之前先通过instanceof判断引用指向的对象是否是该类型

 

 

1.抽象方法:

1)由abstract修饰

2)只有方法的定义,没有方法具体的实现(连{}都没有)

2.抽象类:抽象类可以包含正常方法

1)由abstract修饰

2)包含抽象方法的类必须是抽象类

不包含抽象方法的类也可以声明为抽象类----我乐意

3)抽象类不能被实例化

4)抽象类是需要被继承的,派生类:

4.1)重写抽象类中的所有抽象方法--变不完整为完整

4.2)也声明抽象类------不常用

5)抽象类的意义:

5.1)封装所有派生类所共有的属性和行为--代码复用

5.2)为所有派生类提供了统一的类型------向上造型

5.3)可以包含抽象方法,为所有派生类提供统一的入口,

派生类的行为不一样,但入口是一致的

3.成员内部类:----单独应用的几率小

1)类中套类,外面的称为Outer外部类,里面的称为Inner内部类

2)内部类通常只服务于外部类,对外不具备可见性

3)内部类对象通常在外部类中创建

4)内部类中可以直接访问外部类的成员,包括私有的

内部类中有个隐式的引用指向了创建它的外部类对象

eg: 外部类名.this.成员变量/方法

4.匿名内部类:

1)若想创建一个类(派生类)的对象,并且该类只需要创建一个对象,

此时该类不必命名,称之为匿名内部类

2)在匿名内部类中访问外部的变量,该变量必须是final的

(jdk1.7(含)以前要求变量必须加final,jdk1.8开始不需要加final)

 

1.package:

1)作用:避免类名冲突问题

2)类的全称为: 包名.类名

3)包名可以有层次结构,同包类中的不能同名

4)建议:包名所有字母都小写

import:

1)同包中的类可以直接访问,

不同包中的类不能直接访问,想访问:

1.1)先import后使用----建议

1.2)类的全称----------太繁琐

2.访问控制修饰符:

1)public:公共的,任何类

2)private:私有的,本类

3)protected:受保护的,本类、子类、同包类

4)默认的:什么也不写,本类、同包类

类的访问修饰符只能是public和默认的

类中成员的访问修饰符如上4种都可以

3.static:静态的

1)静态变量:

1.1)由static修饰

1.2)属于类,存储在方法区中,只有一份

1.3)常常通过类名点来访问

1.4)何时用:所有对象所共享的数据(图片、音频、视频等)

2)静态方法:

2.1)由static修饰

2.2)属于类,存储在方法区中,只有一份

2.3)常常通过类名点来访问

2.4)静态方法没有隐式的this传递,

所以静态方法中不能直接访问实例成员

2.5)何时用:方法的操作仅与参数相关而与对象无关

3)静态块:

3.1)由static修饰

3.2)属于类的,在类被加载期间自动执行

因类只被加载一次,所以静态块只执行一次

3.3)何时用:初始化静态资源(图片、音频、视频等)

4.final:最终的、不可改变的-----单独应用几率很小

1)修饰变量:变量不可被改变

2)修饰方法:方法不可被重写

3)修饰类:类不能被继承

5.static final:常量,应用率高

1)必须声明同时初始化

2)通过类名点来访问,不能被改变

3)建议:常量所有字母都大写,多个单词用_分隔

4)编译器在编译时会将常量直接替换为具体的值,效率高

5)何时用:有一些数据经常使用,并且永远不变

 

 

 

 

1.向上造型:

1)超类型的引用指向派生类的对象

2)能点出来什么,看引用的类型

2.方法的重写(Override):重新写、覆盖

1)发生在父子类中,方法名称相同,参数列表相同,方法体不同

2)重写方法被调用时,看对象的类型

3.重写与重载的区别:---------常见面试题

1)重写(override):

1.1)发生在父子类中,方法名称相同,参数列表相同,方法体不同

重写对返回值有要求,不可以不同

1.2)重写遵循"运行期"绑定,看对象的类型来调用方法

2)重载(overload):

2.1)发生在一个类中,方法名称相同,参数列表不同,方法体不同,

重载对返回值没有要求,可以相同,也可以不同

2.2)重载遵循"编译期"绑定,看参数的类型来绑定方法

 

 

 

1.引用类型数组:

1)Student[] stus = new Student[3];

stus[0] = new Student();

2)int[][] arr = new int[3][];

arr[0] = new int[2];

2.继承:抽共性

作用:减少重复,有利于复用性

extends

超类:共有的 派生类:特有的

派生类继承超类后,派生类具有:派生类+超类

单一继承、传递性

派生类构造中必须通过super调用超类的构造

3.super:指代当前对象的超类对象

super.成员变量名------访问超类的成员变量

super.方法名()--------调用超类的方法

super()---------------调用超类的构造方法

 

 

1.方法的重载(Overload):

1)发生在一个类中,方法名称相同,参数列表不同

2)编译器在编译时根据方法的签名自动绑定调用的方法

2.构造方法:构造函数、构造器、构建器

1)给成员变量赋初值

2)与类同名,没有返回值类型

3)在创建对象时被自动调用

4)若自己不写,则默认无参,若自己写了,则不再默认提供

5)可以重载

3.this:指代当前对象,哪个对象调用方法指的就是哪个对象

方法中,方法中访问成员变量之前默认有个this.

this.成员变量名----------访问成员变量

this.方法名()------------调用方法

this()-------------------调用构造方法

4.引用类型画等号:指向同一个对象,会影响

基本类型画等号:赋值,不会影响

5.null:空,没有指向任何对象

若引用的值为null,则该引用不能再进行任何操作了

若操作则NullPointerException空指针异常

 

 

 

ArrayList和LinkedList的区别以及优缺点

1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。

2.对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

 

1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对 ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是 统一的,分配一个内部Entry对象。

2.在ArrayList集合中添加或者删除一个元素时,当前的列表所所有的元素都会被移动。而LinkedList集合中添加或者删除一个元素的开销是固定的。

3.LinkedList集合不支持 高效的随机随机访问(RandomAccess),因为可能产生二次项的行为。

4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

 

List:1.可以允许重复的对象。

    2.可以插入多个null元素。

        3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。

        4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。

 

 Set:1.不允许重复对象

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

        3. 只允许一个 null 元素

        4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。

 

1.Map不是collection的子接口或者实现类。Map是一个接口。

2.Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。

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

4. Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。

5.Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)

 

 

2.面试题:什么场景下使用list,set,map呢?

(或者会问为什么这里要用list、或者set、map,这里回答它们的优缺点就可以了)

答:

  1. 如果你经常会使用索引来对容器中的元素进行访问,那么 List 是你的正确的选择。如果你已经知道索引了的话,那么 List 的实现类比如 ArrayList 可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。
  2. 如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是 List,因为 List 是一个有序容器,它按照插入顺序进行存储。
  3. 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
  4. 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。

 

 

SpringMVC的执行流程

1、用户向服务器发送请求,请求被SpringMVC的前端控制器DispatcherServlet截获。

2、DispatcherServlet对请求的URL(统一资源定位符)进行解析,得到URI(请求资源标识符),然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象,包括Handler对象以及Handler对象对应的拦截器,这些对象都会被封装到一个HandlerExecutionChain对象当中返回。

3、DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。HandlerAdapter的设计符合面向对象中的单一职责原则,代码结构清晰,便于维护,最为重要的是,代码的可复制性高。HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法。

数据验证:验证数据的有效性如长度、格式等,验证结果存储到BindingResult或Error中。

5、Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图模型。

6、根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet。

7、ViewResolver结合Model和View来渲染视图。

8、将视图渲染结果返回给客户端。

 

HashMap和Hashtable的区别

HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

  1. HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
  2. HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  3. 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
  4. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
  5. HashMap不能保证随着时间的推移Map中的元素次序是不变的。

 

HashMap的原理:

HashMap是查询速度最快的数据结构,内部使用

* 数组存放元素.但是HashMap是根据key这个元素

* 的hashcode值决定这组键值对在数组中的位置

* 并进行保存,取的时候就可以直接将key元素的

* hashcode值计算位置从数组中取出,省去了直接

* 使用数组需要遍历查找元素的步骤.

*

* 由于作为key的元素的hashcode决定其在HashMap

* 内部数组位置,而equals决定key是否重复,那么

* 这两个方法直接决定了HashMap中是否会出现

* 链表的情况.

* 当两个Key的hashcode值相同时,它们经过散列

* 算法计算后在数组中的位置一定是一样的,但是

* 若equals比较不为true,那么HashMap认为这是

* 两个不同的key,则会在数组该位置用链表的结构

* 保存这两组键值对.遍历链表会降低HashMap的

* 查询性能.所以要尽量避免.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值