Java基础

1、简述什么是面向对象。

面向对象主要是把事物给对象化,包括其属性和行为。面向对象编程更贴近实际生活的思想。总体来说面向对象的底层还是面向过程,面向过程抽象成类,然后封装,方便使用就是面向对象。

2、面向对象的特点。

封装:将类中的成员(属性,方法,构造器) 设为private,只能在当前类的内部使用,外部无法访问。
继承:子类继承父类的属性和方法。继承之后,在子类中就不需要再定义父类中的属性和方法。减少重复代码的编写,提高了代码的重用性。
多态:一个方法在执行时,根据传入对象的不同,执行结果不同。
抽象:是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面,抽象只关注对象的哪些属性和行为,并不关注这此行为的细节是什么,不能实例化。

3、String、StringBuffer、StringBuilder区别。

String对象保存的字符串是不可修改的。
StringBuffer和StringBuilder对象保存的字符串是可以修改的。
StringBuffer是线程安全的,执行效率低;StringBuilder是线程不安全,执行效率高。

4、List、Set、Map区别

  • List 集合中对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象,例如通过list.get(i)方法来获取集合中的元素;
  • Map 中的每一个元素包含一个键和一个值,成对出现,键不可以重复,值可以重复;
  • Set 集合中的对象不按照特定的方式排序,并且没有重复对象,但它的实现类能对集合中的对象按照特定的方式排序,例如 Tree Set 类,可以按照默认顺序,也可以通过实现 Java.util.Comparator< Type >接口来自定义排序方式。

5、HashMap的实现原理。

基于hashing的原理,jdk8后采用数组+链表+红黑树的数据结构。通过put和get存储和获取对象。当给put()方法传递键值时,先对键做一个hashCode()的计算来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键的equals()方法找到正确的键值对,然后再返回值对象。

6、字节流和字符流的区别。

(1)字节流以字节为单位进行读写,字符流是以字符为单位进行读写。
(2)字节流写操作立即执行,字符流写操作需要调用flush或close方法时才执行。
(3)字节流可以传输任何类型的数据(文本、图片、音频、视频==),字符流只能传输字符数据(文本)。

7、异常的处理方式有哪些。

异常上抛:在方法声明的位置上,使用throws关键字,抛给上一级;只能解决编译期异常(非运行时异常),编译可以通过,但是运行时还是可能会出现该异常导致程序中止。
异常捕捉:使用try…catch语句进行异常的捕捉;既可以解决编译期异常,还能解决运行时异常,程序可以继续运行。

8、TCP和UDP区别。

1、TCP是面向连接的协议,发送数据前要先建立连接,TCP提供可靠的服务,也就是说TCP连接传输的数据不会丢失,没有重复,并且按顺序到达;
2、UDP是无连接的协议,发送数据前不需要建立连接,无可靠性;
3、TCP通信类似于打电话,接通了确认身份后,才开始进行;
4、UDP通信类似于学校广播,靠着广播播报直接进行通信;
5、TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多;
6、TCP是面向字节流的,UDP是面向报文的;
7、TCP首部开销(20字节)比UDP首部开销(8字节)要大;
8、UDP的主机不需要维持复杂的连接状态表。

9、线程的创建方式有哪些。

方式1:通过继承Thread类创建线程
方式2:通过实现Runnable接口创建线程
方式3:使用Callable和Future来创建线程
方法4:通过线程池来创建线程

10、线程同步的方式有哪些。

1、使用synchronized修饰的同步方法。阻塞式的同步。会自动释放锁。
2、同步代码块。
Lock锁。能完成synchronized所实现的所有功能。还有着更精确的线程语义和更好的性能。锁需要程序员在finally语句中手动释放。

11、简述线程的生命周期。

线程的生命周期包含5个阶段,包括:新建、就绪、运行、阻塞、销毁。
新建:就是刚使用new方法,new出来的线程;
就绪:就是调用的线程的start()方法后,这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;
运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能;
阻塞:在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;
销毁:如果线程正常执行完毕后或线程被提前强制性的终止或出现异常导致结束,那么线程就要被销毁,释放资源;

12、java有哪几种线程池。

newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就会创建一个工作线程,如果工作线程数量达到线程池初始的最大值,则将提交的任务存入到池队列中。
newCachedThreadPool创建一个可缓存的线程池。工作线程的创建数量几乎没有限制,如果长时间没有往线程池中提交任务,则该工作线程自动终止。之后你又提交新的任务,则线程池重新创建一个工作线程。
newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行。
newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行。

13、List实现类有哪些,区别是什么?

ArrayListVector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及元素移动等内存操作,所以索引数据快而插入数据慢。Vector由于使用了synchronized方法(线程安全),通常性能上比ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需记录本项的前后项即可,所以查询慢插入快。

14、请你谈谈GC垃圾回收机制

GC是垃圾收集机制。垃圾回收可以有效地防止内存泄漏,有效地使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时地调用垃圾回收器对某个对象或所有对象进行垃圾回收。但是可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会立刻执行。回收机制分为代复制垃圾回收、标记垃圾回收和增量垃圾回收。

15、请你谈谈类加载的过程。

1、类的加载:将类的Class文件加载到内存中,并为其生成Java.lang.class对象(由类加载器完成)
2、类的链接:将Java类的二进制数据合并到jvm运行状态中
  1)验证:确保类符合JVM规范,保证安全性
  2)准备:为类变量分配内存和初始化值
  3)解析:JVM常量池中的符号引用(常量名)直接替换成直接引用地址
3、类的初始化:JVM对类进行初始化
执行类构造器方法(这个方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的(该类构造器是构造类信息的,不是构造对象的构造器))
当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化
JVM会保证一个类的方法在多线程环境中被正确加锁和同步

16、请你谈谈jvm的内存分配。

根据各种数据的特性JVM从逻辑上把内存划分成了几个区域,分别为方法区、虚拟机栈、本地方法栈、程序计数器、堆 5个区域。

17、jdk1.8的新特性有哪些?

Lambda表达式:Lambda允许函数作为参数传递到方法中。
方法引用:可以直接引用已有Java类或对象的方法或构造器。
Date Time API:加强对日期与时间的处理。
Optional类:用来解决空指针异常。
JavaScript引擎:允许程序在JVM上运行特定的javascript应用。
默认方法:可以理解为一个在接口里面有了一个实现的方法。
新工具:加入像是Nashorn引擎 jjs、 类依赖分析器jdeps的新的编译工具。
Stream API:可以把函数式编程风格引入到Java中。

18、NIO是什么?

Java NIO全称java non-blocking IO, 是指JDK提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NIO(即New IO),是同步非阻塞的
NIO有三大核心部分: Channel(通道), Buffer(缓冲区),Selector(选择器)
NIO是面向缓冲区,或者面向块编程的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络。

19、Map实现类有哪些,区别是什么?

Map接口主要用四种实现类。分别是HashMap,Hashtable,linkedHashMap,ConcurrentHashMap。
HashMap:它的底层实现是数组+链表,key和value都可以储存null。线程不安全,但效率较高
Hashtable:它的底层实现是数组+链表,key和value不可以存储null。线程安全,但效率较低。
ConcurrentHashMap:它的底层实现是分段数组+链表。Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。
linkedHashMap:LinkedHashMap是HashMap的子类。它的元素按照插入顺序排列。遍历速度较慢。

20、常用的排序算法有哪些?
冒泡、插入、选择、快速、归并、桶……

21、常用的数据结构有哪些?

数组、栈、队列、链表、树、图、字典树、散列表。

22、jvm优化

设定堆内存大小
设定新生代大小
设定垃圾回收器

23、基本类型和引用类型的区别

1、从概念方面说

  • 基本数据类型:变量名指向具体的数值
  • 引用数据类型:变量名指向内存地址

2、从内存的构建方面说

  • 基本数据类型:被创建时,在栈内存中会被划分出一定的内存,并将数值存储在该内存中。
  • 引用数据类型:被创建时,首先会在栈内存中分配一块空间,然后在堆内存中也会分配一块具体的空间来存储数据的具体信息,即hash值,然后由栈中引用指向堆中的对象地址。

3、从使用方面来说

  • 基本数据类型:判断数据是否相等,用==判断。
  • 引用数据类型:判断数据是否相等,用equals()方法,==是比较数值的,而equals()方法是比较内存地址的。

24、自动装箱和拆箱

基本类型和包装类 之间转换,jdk1.5我们提供了装箱和拆箱技术。
装箱:将一个基本类型的数据转换为包装类的对象。
拆箱:将一个包装类的对象转为基本类型数据。

25、instanceof 关键字的作用
对象名 instanceof 类名

instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

26、泛型是什么

泛型是Java SE 1.5之后的特性,“泛型”意味着编写的代码可以被不同类型的对象所重用。以集合为例,使用泛型的好处是我们不必因为添加元素类型不同而定义多个集合。

27、重载和重写的区别

重写发生在父类与子类之间,方法名,参数列表,返回类型必须相同。访问修饰符的限制一定要大于被重写方法的访问修饰符。重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。
重载是一个类中多态性的一种表现。要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序),对返回值类型没有要求。

28、== 与 equals区别

==对于基本类型来说是值比较,对于引用类型来说比较的是引用;而equals默认情况下是引用比较,只是很多类重写了equals方法,比如String,Integer等把他变成了值比较,所以一般情况下equals比较的是值是否相等。

29、HashSet如何去重?

HashSet类的源码中维护了一个HashMap对象和一个PRESENT空对象,add方法将元素的值作为map的key,将PRESENT变量作为map的value,这个变量只作为存放map时的一个占位符,故HashSet中的元素去重其实是利用了HashMap中的key不能重复的特性。
HashMap保证key不重复,是因为其内部进行了对象的hashcide和equals方法的判断。HashMap在插入值时,首先通过hash计算元素的位置,然后判断该位置是否有值,如果没有值,则直接插入,若有则需要通过该对象的hashcode和equals方法来判断是否为重复元素,由于String类的equals方法不是比较该对象的地址值所以需要重写对象的equals和hashcode方法。

30、final, finally, finalize的区别

final:常量用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
finally:异常处理机构 异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,供垃圾收集时的其他资源回收,等操作。

31、Java反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

32、常用的设计模式
Java中有23种设计模式,其中常用的有:

工厂模式:``BeanFactor就是简单工厂模式的体现,用来创建对象的实例
单例模式:Bean默认为单例模式
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
模板方法模式:用来解决代码重复问题,例如RestTemplate、JpaTemplate
观察者模式:定义对象键一种一对多的依赖关系,当一个对象状态发送改变时,所有依赖与它的对象都会得到通知并自动更新,如Spring中listencer的实现–ApplicationListener

33、什么是序列化?序列化有什么好处。

该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

34、浅拷贝与深拷贝

浅拷贝只复制某个对象的引用,而不复制对象本身。
深拷贝会创造一个一摸一样的对象,新对象和原对象不共享内存,修改新对象不会改变原对象。

35、try catch finally,try里有return,finally还执行么?

执行,并且 finally 的执行早于 try 里面的 return。

36、error和exception区别

error表示恢复不是不可能但很困难的一种严重。比如说内存溢出。不可能指望修改程序去处理这样的情况。
exception表示一种设计或实现问题。也就是说,他表示如果程序运行正常,从不会发生的情况。

37、堆和栈的区别
JVM中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常比堆小,也不会在多个线程之间共享,而堆被整个JVM的所有线程共享。

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作他用。
用来存放new出来的对象和数组,在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象,引用变量就相当于是为数组或对象起的一个名字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值