Java基础面试题

1.string 和 stringbuffer 和 stringbuilder
1.运行速度 :StringBuilder>StringBuffer>String
2.线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
3.使用场景:
String适用于少量字符串操作
StringBuilder使用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer适用于多线程下在字符缓冲区进行大量操作的情况

2.JDK和JRE的区别

​ java运行环境(java Runtime Enviroment)试运行java程序的基本的java虚拟机,包括执行applet的浏览器插件。JDK(java Development Kit)是为了开发,编译和执行java应用程序。

​ 1.jdk是Java的开发工具包,jdk中包含了jre

​ 2.jdk是整个Java开发的核心,包括了Java运行环境,Java工具和Java基础类库

​ 3.jre是Java程序的运行后台,面向Java程序的使用者,而不是开发者

​ 4.jre是可以在Java上运行,测试和传输应用程序的Java平台,它包括Java虚拟机(JVM)

​ Java核心类库和支持文件,它不包括开发工具,调试器和其他工具

​ jdk=jre+java开发工具(javac.exe,java.exe,javadoc.exe)

​ jre=jvm+java核心类库

2-1:什么是JVM?为什么称java为跨平台的编程语言?

​ java虚拟机(Java Virtual Machine)是可以执行java字节码的虚拟机,每个java源文件将编译成字节码文件,然后在JVM中执行,java之所以被设计成可以在任意的平台上运行,而不需要重写或者在不同的平台下重新编译,这些都要归功于java虚拟机,因为JVM非常了解特定的指令的长度以及底层硬件平台的特殊性。

2-3:描述一下JVM加载class文件的原理机制

​ JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader是一个重要的java运行时的系统组件,它负责在运行时查找和装入类文件的类。

3.Java的垃圾回收机制

​ C++中垃圾回收是人工手动回收的,工作量大,可控性高

​ Java中垃圾回收机制是自动回收的,可控性差,还会有内存溢出的情况(因为自动分配空间的时候内存 对象过多)

​ Java中垃圾回收可以用system.gc()进行调用回收,并不是一定能回收成功。

用引用计数法( 当前jvm中未采用)和可控性分析算法来确定哪些对象应该回收

​ 引用计数法:给对象添加一个引用计数器,每当对他进行引用的时候,计数器就加一,当引用失效 时,计数器就减一,计数器为零时,表示此对象没有被引用,就会被gc进行回收,但是在当前jvm中并 没有采用,因为不能解决对象之间循环引用(两个垃圾互相引用)的问题。

​ 可控性分析算法:通过判断对象的引用链是否可以被回收。从离散数学中的图论引入的,程序将所 有引用关系看做一张图,通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜 索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连(就是从 GC Roots 到这个对 象不可达)时,则证明此对象是不可用的。

在确定回收对象后,jvm会在cpu空闲的时候进行回收,存储满后,也会主动调用system.gc() 进行尝试 回收。

用标记-清除算法、复制算法、标记-整理算法、分代收集算法(新生代,老年代,永久代在jdk1.8后被废除,Java提供了“元空间”新技术);

回收算法的优缺点:

​ ①标记-清除算法:

​ 简单,效率不高,仅对不存活的对象进行处理,空间浪费,会产生大量不连续的内存碎片,当放其 他对象时,放不下,所以产生的内存碎片就不能用了。

​ ②复制算法:

​ 不用考虑碎片问题,代价是内存将缩小一半。

​ ③标记-整理算法:

​ 和清除算法运行原理相似,还会对存活对象进行整理,不会产生碎片。

​ ④分代收集算法(jvm使用最多):

​ 新生代用复制算法就可完成对存活对象的收集

​ 老年代存活率高,没有额外空间进行分担担保,用标记-清除or标记-整理算法收集。

4-0:List和Map的区别

​ list是存储单列数据的集合,map是存储以键值对这样的双列数据的集合,list中存储的数据是有顺序的,并且允许重复,map中存储的数据是没有顺序的,并且不允许重复。

4-1.arrayList和Vector的区别

​ 首先这两个类都实现了List接口,list接口继承了collection接口,都是有序的集合,可以按照位置索引号取出某个元素,数据是允许重复的,与HashSet 最大的区别就是HashSet不允许有重复的元素。

​ 同步性:

​ Vector和HashTable都是旧的,java诞生的时候就存在,是线程安全的,效率低于新的,而ArrayList 和HashMap都是java2 之后才提供的,是线程不安全的,效率高于老的(单线程情况下)。

​ 数据增长方面:

​ ArrayList和Vector都有初始容量,在存储满之后,二者都会自动增长,Vector增长为原来的一倍,ArrayList增长原来的0.5倍。

5.HashTable和HashMap的区别

​ HashTable是旧的,效率低,线程安全。HashMap是新的,效率高(二者比较下,在单线程情况下),线程是不安全的。

HashMap允许空(null)键值(key),HashTable不允许。

6.ArrayList和LinkedList的区别

​ ArrayList底层是基于动态数组实现的,在存储满时会自动进行扩容(扩容为原来的1.5倍),避免内存溢出,减少出错几率。

​ LinkedList底层是基于链表的动态数组实现的,访问时需要用mode()函数进行遍历链表。

​ arraylist删除某个list元素后,数组中的元素需要全部重新排序(数组拷贝),而linkedlist只需要更改指针的指向就行了。

​ 新增:linkedlist生成了一个Entry元素,修改了相邻元素的next和previous引用指向自己,ArrayList把元素追加到了数组中而已,性能差别很微小。

​ 删除:ArrayList根据下标删除指定位置上的元素,linkedlist删除提供了删除指定位置元素,删除头元素,这是双向链表的标准删除算法,全部是引用算法的变更,实际测试中,处理大批量删除操作动作时,linkedlist比ArrayList快40倍以上。

​ 修改 : linkedlist输给ArrayList,linkedlist是顺序存取,不然要遍历才能定位元素,耗时,ArrayList根据指定位置,找到并修改。

​ 在写方面,linkedlist占优势。

​ 查 :当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。

6-1:List、set、Map三个接口,存取元素时,各有什么特点?

​ list和set具有相似处,都是单列元素集合,他们有一个共同的父接口,叫Collection。

​ set里不允许有重复的元素,也是无序的,set取元素时,只能用iterator接口取得所有元素,再逐一遍历各个元素。

​ list表示有先后顺序的集合,根据插入先后顺序排序,但是也可以插队,用add(int index,Obj e)方法。list也可以用Iterator接口取得所有元素进行遍历,也可以调用get(index i)来明确取哪一个。

​ map和list与set最大的区别是,它是双列集合,有put(obj key, obj value)方法进行存储,不能存储重复的key,取时根据get(obj key) 进行取,返回值为key所对应的value,还可以获得键值对祝贺,用map.Entry对象。

6-2:说出ArrayList、Vector、LinkedList的存储性能和特性

​ ArrayList和vector都是用数组方式存储数据的,数组的大小要大于实际的大小,便于增加和插入,它们都允许按照序号索引元素,但是在中间插入元素或删除除了最后的元素,都要进行数据的移动,索引快,插入慢。

​ 而LinkedList使用的是双向链表实现存储,按序号索引要进行向前或向后的遍历,但是插入数据是只需记录本元素的前后即可,所以插入速度较快。

6-3:两个对象的值相同(x.equals(y)==true),但是却可有不同的hashcode,这句话对不对?

​ 不对

​ hashcode方法中规定:相等的对象必须具有相同的哈希码,但是有相同的hashcode,并不一定相同。

​ 首先equals方法必须要满足自反性(返回true或false)、对称性(反过来比较结果也一样)、传递性(x和y相等,y和z相等,那么x和z也要相等)、一致性(多次调用返回同样的结果)、而且对于任何非null值的引用(x.equals(null))都必须返回false;

​ 当要重写equals方法时,其中语言规定了也要重写hashcode方法,为了保持一致性。

​ hashcode是为了避免集合中的元素重复时频繁调用equals来进行比较,使得效率降低,来引入的,hashcode方法返回的实际上就是对象存储的物理地址,每个对象都有一个默认的哈希码,当插入时只需要比较插入对象的哈希码是否存在即可。

6-3:实现高质量的equals方法的诀窍包括:

​ 1.使用==操作符检查参数是否为这个对象的引用;

​ 2.使用instanceof操作符检查“参数是否为正确的类型”;

​ 3.对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;

​ 4.编写完equals方法后,思考是否满足对称性、传递性、一致性;

​ 5.重写equals时总要重写hashCode;

​ 6.不要将equals方法参数的object对象替换为其他的类型,在重写时不要忘掉@Override注解;

6-4:说出一些常用的类,包,接口

​ 类:String,Integer,system,Class,bufferedReader,file,list,hashMap

​ 包:java.long java.util java.sql javax.servlet org.omg

​ 接口:list map document httpsession collection set iterator

7.接口和抽象类的区别

​ 含有abstract修饰符的class即为抽象类,抽象类和普通类的唯一区别是不能创建实例对象和可以有抽象方法,抽象类中的方法不必是抽象的,不能有抽象静态构造方法和抽象静态方法。

​ 接口是抽象类的一种特例,接口中所有方法必须是抽象的,方法定义默认为 public abstract 类型的,成员变量默认为 public static final 类型的。

​ 接口中不能有构造方法、普通成员变量、普通方法、静态方法。方法的访问类型只能是默认的public的,抽象类可以有。抽象类和接口都可以包含静态成员变量。

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

​ 接口更多是在系统架构设计方法发挥作用,抽象类主要在代码实现方面发挥作用,可以实现代码的重用。例如模块方法设计模式(父类方法中间的某段代码不确定,留给子类干)。

8.简述对ConcurrentHashMap的理解以及和hashMap的区别

​ ConcurrentHashMap 是在hashMap的基础上,ConcurrentHashMap将数据分成多个segment,默认16个,然后每次操作对一个segment加锁,避免多线程锁的几率,让锁的粒度更精细一点,提高并发效率,用哪部分就锁哪部分。

​ hashMap的Key和Value可以为null,但是ConcurrentHashMap的key和value不能为空。

9.“==”和equals方法的区别

​ ==操作符用来比较两个变量的值是否相等,比较基本变量,引用变量(比较的是地址)只能用 == 操作符。

​ equals是用于比较两个独立的对象的内容是否相等,就好比比较两个人的长相(内容),而不是比较两个人的名字(引用地址)是否相等。

10.说说&和&&的区别

​ &和&&都可以用作逻辑与运算符来使用,区别是&&具有短路的功能,a&&b 当a 为false时,就直接返回false,不会计算后面的表达式。

​ &还可以用作位运算符,当两边的表达式不是boolean型时,&表示按位与操作,例如 0x31 & 0x0f = 0x01。

11.Overload和Override的区别,Overloaded的方法是否可以改变返回值的类型

​ overload是重载的意思,override是重写的意思。

​ 重写override表示一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同,参数个数,顺序,类型。

​ 重载overload表示子类中可以与父类中的某个方法的名称和参数完全相同。相当于将父类方法覆盖了,这是面向对象编程的多态性的一种表现,子覆盖父类时,只能抛出更少的异常,访问权限只能比父类的大。

​ 重载不可以改变返回值类型,如果改变就会出现方法名参数完全一个的方法,而返回类型不同,java就无法确定编程者到底要调用哪个方法了,以为它无法通过返回值类型判断。

​ 重写(覆盖)要注意:

​ 覆盖方法的标志,返回值,抛出异常必须和被覆盖方法保持一致。

​ 被覆盖的方法不能是private,否则就是重新定义了一个方法。

​ 重载要注意:

​ 不同的参数类型,个数,顺序,同一个方法内的几个参数类型必须不一样。

​ 不能通过访问权限,返回类型,抛出的异常进行重载。

​ 方法的异常类型和数目不会对重载产生影响。

12.面向对象的特征有哪些方面

​ 封装:

​ 封装是保证软件部件具有优良的模块性的基础,目标是实现软件部分的“高内聚,低耦合”,在面向对象编程中,对象是疯转的最基本单位,封装就是把一个对象的属性和行为的代码封装到一个模块中,属性用变量定义,行为用方法进行定义,把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和他操作的数据放入同一个类中。

​ 继承:

​ 在一个已经存在的类的基础上进行,将存在类的内容作为自己的内容,并加入若干新的内容,或者修改为更合适的内容,只就是继承,提高了软件的可重用性和可扩展性。

​ 抽象:

​ 抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处。

​ 多态:

​ 同一操作作用于不同的对象,可以产生不同的效果,这就是多态,比如 用刀切这个动作,厨师用刀切,医生用刀做手术切,多态的好处是增强了软件的灵活性和扩展性。

13.java线程

1.java线程和进程的区别:

​ 进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的 基本单位。

​ 线程:是进程的一个执行单位,市金城内部调度实体,比进程更小的独立运行的基本单位。线程也被称之为轻 量级进程。一个程序至少一个进程,一个进程至少一个线程。

​ 区别:

​ 地址空间:同一进程的线程共享本进程的地址空间,而进程之间的资源是独立的地址空间。

​ 资源拥有:同一进程的线程共享本进程的资源,但是进程之间的资源是独立的。

​ 进程崩溃,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比 多线程健壮。

​ 进程切换时,消耗的资源大,效率高。所以涉及频繁切换时,使用线程要好于进程。同时进行并且又要共 享某些变量的并发操作,只能用线程不能用进程。

​ 进程都有一个程序运行的入口,线程不能独立执行,必须依赖进程。

​ 线程是处理器调度的基本单位,但是进程不是。

​ 进程和线程都可以并发执行。

​ 优缺点:
​ 线程执行开销小,但是不利于资源的管理和保护。

​ 进程执行开销大,但是能够很好的进行资源管理和保护,进程开一个跨机器迁移。

2.多线程有几种实现方法?有什么区别?

​ 1.继承Thread类

​ 2.实现Runnable接口(Callable接口)

​ 一个类如果实现了Runnable接口或者继承了Thread类,那么它就是一个多线程类,如果要实现多线程,还需要 重写run()方法,所以run() 方法是多线程的入口。

​ 区别:

​ 1.Thread是runnable接口的自雷,实现了Runnable接口的方式解决了java单继承的局限

​ 2.Runnable接口实现多线程比继承Thread类更加能描述数据共享的概念。

​ 多线程有几种实现同步的方法?

​ 两种,分别是synchronized,wait与notify

​ wait():使一个线程处于等待状态,并且释放所持有的对象的锁。

​ sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕获interruptedException异常, 不会是释放锁。

​ notify():唤醒一个处于等待状态的线程,在调用此方法的饰扣,并不能确切的唤醒某一个等待状态的 线程, 而是有JVM虚拟机来确定唤醒哪个线程,而且不是按优先级。

​ Allnotity():唤醒所有处于等待状态的线程,不是给所有唤醒线程一个对象的锁,而是让他们去竞 争。

3.产生死锁的原因?

​ 产生死锁的四个必要条件:

​ 1、互斥条件:一个资源每次只能被一个进程使用。

​ 2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

​ 3、不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。

​ 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

4.如何避免死锁?

​ 按照同一顺序访问对象,避免事务中的用户交互,保持事务简短并处于一个批处理中,使用较低的 隔离级别,使用基于行版本控制的隔离级别,使用绑定连接。

5.run和start的区别

​ 1.start()是线程的启动者,start() 在java.long.Thread类中定义,它统计了一个新进程,线程从New State移动到Runnable状态,当线程有机会执行时,它的目标run() 方法将会执行。

​ 2.run()是线程任务的运行者,run()方法在java.long.Runnable接口中定义,必须要实现类中重写,run 是Runnable接口的一个抽象方法,由java虚拟机直接调用的,不会创建的新线程。

​ 当程序调用start()方法时,会创建一个新线程,然后执行run()方法,直接调用run()方法,则不会创 建新的进程,run()方法将作为当前调用线程本身的常规方法调用执行,并且不会发生多线程。

​ start()方法不能多次调用,否则抛出java.long.lllegalStateException;而run()方法可以进行多次调用,因 为它只是一种正常的方法调用。

6.什么叫线程安全?

​ 当多个线程访问某个方法时,不管你通过怎样的调用方式或者说这些线程如何交替的执行,我们在 主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们可以说这个类 是线程安全的。

7.java中如何保证多线程的安全

​ 线程安全的问题主要体现在:

​ 原子性:一个或者多个操作在CPU执行的过程中不被中断的特性。

​ 可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到。

​ 有序性:程序执行的顺序按照代码的先后顺序执行。

​ 导致原因:

​ 缓存导致的可见性问题、线程切换带来的原子性问题、编译优化带来的有序性问题。

​ 解决办法:

​ jdk Atomic开头的原子类、synchronized、lock 可以解决原子性问题(执行过程中不被中断)。

​ synchronized、volatile、lock 可以解决可见性问题。

​ Happens-Before 规则可以解决有序性问题。

​ Happens-Before 规则如下:

​ 程序次序规则:在一个线程内,按照程序控制流顺序,书写在前面的操作先行发生于书写在后 面的操作。

​ 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。

​ volatile变量规则: 对一个volatile变量的写操作先行发生于后面对这个变量的读操作。

​ 线程启动规则:Thread对象的start() 方法先行发生于此线程的每一个动作。

​ 线程终止规则:线程中的所有操作都先行发生于对此线程的终止检测。

​ 线程中断规则:对线程interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发 生。

​ 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的 开始。

14.java反射常见面试题

1.什么是反射

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

2.哪里用到反射机制

​ 1.JDBC中,利用反射动态加载了数据库驱动程序。(Class.forName(“jdbc:XXXX.oracle”))

​ 2.Web服务器利用反射调用了Servlet的服务方法。

​ 3.开发工具利用反射动态剖析对象的类型与结构,动态提示对象的属性和方法。

​ 4.很多框架都用到了反射机制,注入属性,调用方法,如spring。

3.什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作?

​ 对象序列化:将对象中的数据编码为字节序列的过程。

​ 反序列化:将对象的编码字节重新反向解码为对象的过程。

​ 注意事项:

​ 1.被序列化的对象类型需要实现序列化接口,此接口为标识接口,没有声明任何的抽象方法, java编译器识别这个接口,自动为这个类添加序列化和反序列化方法。

​ 2.为了保持序列化过程的稳定,建议在类中添加序列化版本号。

​ 3.不想让字段放在硬盘上就加transient。

​ 使用序列化的场景:

​ 1.想把内存中的对象保存到一个文件中或者数据库中的时候。

​ 2.想用套接字在网络上传送对象的时候。

​ 3.想通过RMI(远程方法调用)传输对象的时候。

4.反射机制的优缺点

​ 优点:可以动态执行,在运行期间根据业务功能动态执行方法、访问属性、最大限度发挥了java的 灵活性。

​ 缺点:对性能有影响,这类操作总是慢于直接执行java代码。

5.动态代理是什么?有哪些作用?

​ 动态代理是运行时动态生成代理类

​ 动态代理的应用有Spring AOP数据查询、测试框架的后端mock、rpc、java注解对象获取等。

6.怎么实现动态代理?

​ 1.JDK原生态代理和cglib动态代理。

​ 2.JDK原生动态代理是基于接口实现的,而cglib是基于继承当前类的子类实现的。

7.java反射机制的作用

  1. 在运行时判断任意一个对象所属的类

  2. 在运行时构造任意一个类的对象

  3. 在运行时判断任意一个类所具有的成员变量和方法

  4. 在运行时调用任意一个对象的方法

    8.如何使用java的反射

1.通过一个全限类名创建一个对象

Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
类名.class; 获取Class<> clz 对象
对象.getClass();

2.获取构造器对象,通过构造器new出一个对象

Clazz.getConstructor([String.class]);
Con.newInstance([参数]);

3.通过class对象创建一个实例对象(就相当与new类名()无参构造器)

Cls.newInstance();

4.通过class对象获得一个属性对象

Field c=cls.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
Field c=cls.getDeclaredFields():获得某个类的所有声明的字段,即包括publicprivate和proteced,但是不包括父类的声明字段

5.通过class对象获得一个方法对象

Cls.getMethod(“方法名”,class……parameaType);(只能获取公共的)
Cls.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
M.setAccessible(true);(让私有的方法可以执行)

让方法执行
1). Method.invoke(obj实例对象,obj可变参数);-----(是有返回值的)

15.switch语句能否作用在byte上,能否作用在long上,能否作用在String 上?

​ switch中参数只能是一个整数表达式或者是枚举常量,整数表达式可以是int 基本类型或integer包装类型,byte,short,char可以隐含的转换为int

byte、short、char>int>long>float>double,从低级转高级类型自动转换(上转型),高级转换低级需要强制类型转换(下转型)。

long和string部门同转换为整数表达式类型,所以不符合switch的语法规定。

16.short s1=1;s1=s1+1;有什么错?short s1=1;s1+=1;有什么错?

​ s1+1运算时会自动提升表达式的类型,所以结果为int基本类型,int基本类型级别高于short 型,编译器会报告需要强制转换类型的错误。

​ s1+=1;+=是java语言规定的运算符,java编译器会对他进行特殊处理,因此可以正确编译。

17.char型变量中能不能存储一个中文汉字?为什么?

​ char型数据变量是用来存储Unicode编码的字符的,Unicode编码字符集中包含了汉字,所以char 可以存储汉字,不过如果有特殊的汉字没有被包含在Unicode编码字符集中的话,就不能存储此汉字,Unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

18.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

​ 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象的内容还是可以改变的。

19.Sting是最基本的数据类型吗?

​ java中八大数据基本类型包括:byte、int、char、long、float、double、boolean和short

java.long.String类是final类型的,不能继承和修改这个类,为了提高效率,节省空间,java提供了StringBuffer类。

20.String s=new String(“xyz”);创建了几个String 对象,有什么区别?

​ 两个或者一个,因为字符串new的对象存放在字符串常量缓冲池中,如果缓冲池中存在了该对象,那么地址就会指向此内存中已经存在的对象,不会创建新的对象,如果不存在就需要重新创建一个此对象,另外,每写一次new String 就会创建对象,xyz也需要创建一个对象,所以是两个或者一个。

21.int和integer的区别

​ integer是int原始数据类型的封装类,包含了很多方法,int的默认值为0,integer的默认值为null,integer能区分出空和0的区别,int则无法表达出未赋值的情况,int不适合作为web层的表单数据的类型。

java为每个原始类型提供了包装类型:

–原始类型:boolean,char,byte,short,int,long,float,double

–包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

从java5开始引入了自动拆装箱机制,二者可以相互转换,如下代码所示:

class AutoUnboxingTest {
    public static void main(String[] args) {
            Integer a = new Integer(3);
            Integer b = 3;                  // 将3自动装箱成Integer类型
            int c = 3;
            System.out.println(a == b);     // false 两个引用没有引用同一对象
            System.out.println(a == c);     // true a自动拆箱成int类型再和c比较
    }
}

另外还有一个面试题:

public class Test03 {
    public static void main(String[] args) {
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        //查看了integer.valueOf()中的InterCache,InterCache是Interger内部类
        //其中代码所示:如果整型字面量的值在-128到127之间,那么不会new新的Integer对象
        //而是直接引用常量池中的Integer对象
        //所以  f1和f2相同的值,引用同一个Integer对象,所以是true;
        System.out.println(f1 == f2);//true 
        //而  f3和f4超出范围,所以重新创建了两个Integer对象,“==”比较的是引用对象的地址,所以是false;
        System.out.println(f3 == f4);//false
    }
}

java流

1.java中有几种流,jdk为每种类型的流提供了一些抽象类以供继承,是哪些?

​ 字符流,字节流

​ 字节流继承于InputStream OutputStream,字符流继承于InputStreamReader OutputStream Writer,在 java.io包中还有其他多种流,主要是为了提高性能和使用方便。

2.java IO分为几种流?
​ 按照流的流向分,可以分为输入流和输出流
​ 按照操作单元划分,可以划分字节流和字符流
​ 按照流的角色划分为节点流和处理流
3.BIO (Blocking I/O): 同步阻塞I/O模式,NIO (New I/O): NIO是一种同步非阻塞的I/O模型,AIO (Asynchronous I/O): AIO 也就是 NIO 2之间 有什么区别?
​ BIO可以让每一个链接都专注于自己的流,简单,缺点是无法应对高并发
​ NIO在java1.4中引入NIO框架,提供Channel、Selector、Buffer抽象,提供了与BIO模型中的Socket和ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像 传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
​ AIO在Java7中引用了NIO的改进版Nio2,为异步非阻塞的IO模型
3.Files的常用方法有哪些?
​ Files.exists() 检测文件路径是否存在
​ Files.createFile() 创建文件
​ Files.createDirectory() 创建文件夹
​ Files.delete() 删除文件或者目录
​ Files.copy() 复制文件
​ Files.move() 移动文件
​ Files.size() 查看文件个数
​ Files.read() 读取文件
​ Files.write() 写入文件

4.字符流和字节流的区别

​ 1.字符流是字节流的包装类,可以直接接受字符串,内部将字符串转成字节,再写入底层设备,底层设备永远只接受字节数据。

​ 2.字节流操作的基本单元为字节,字符流操作的基本单元是两个字节的Unicode字符

​ 3.字节流默认不使用缓冲区,字符流使用缓冲区,因为字节流是文件直接操作的,字符流要通过缓冲区操作文件。

​ 4.字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入及读取Unicode码元。

Java内存

1.heap和stack有什么区别

​ 栈(stack)内存,栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属的存储空间,用于存 储这个方法内部的局部变量(基本数据类型变量,一个对象的引用,语句中的变量,函数上的参数),函数调用的现 场保存,都使用栈,当方法结束时,空间会释放。栈空间用光了会引发StackOverflowError。

​ 堆(heap)内存,堆一般存放new出来的对象,不会随着方法的结束而消失,堆是垃圾收集器管理的主要区 域,由于现在的垃圾收集器都采用的分代收集算法,所有堆还可以分为新生代和老年代,再具体一点可以分 Eden、 Survivor、Tenured,堆和常量池 空间不足会引发OutOfMemoryError。

​ 方法区:方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息,全局变量,常量,静态变量,JIT编译器编译后的代码等数据;常量池是方法区的一部分,字面量如“Hellow”、100都是存放在常量池中;

​ 栈空间操作起来最快但是栈很小;

​ 使用final修饰过的局部变量则放在堆中。

2.java中一共分为几块内存片

​ 寄存器:供CPU使用;

​ 本地方法区:调用系统底层内容;

​ 方法区:(也叫数据区,共享区,共享数据区)存放全局变量,静态变量和字符串常量和方法;

​ 栈:存储的都是局部变量(函数中定义的变量,函数上的参数,语句中的变量),一个对象的引用,运算完成 后,会释放空间;

​ 堆:存储数组和对象,实体,new出来的;每一个实体的内存首地址值,变量默认值,垃圾回收机制的主要区域

Java异常

​ 1.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值