java常见面试题总结

float f=3.4;是否正确?

不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。

小数默认为双精度 double的。双精度向单精度转换。会导致精度损失的

short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。

而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。

int和Integer有什么区别?

Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

int 默认值为0,Integer默认值为null

        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比较

        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;

        System.out.println(f1 == f2);

        System.out.println(f3 == f4);

f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf

如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中f1==f2的结果是true,而f3==f4的结果是false。

&和&&的区别?

二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。

&&称为短路运算:如果左边为false,那么就不再判断右边的了。

&与运算左边为什么都会去判断右边的结果。

解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。

栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间

String str = new String("hello");

上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。

Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

用最有效率的方法计算2乘以8?

2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

数组有没有length()方法?String有没有length()方法?

数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。

构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载。

两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

值相同 hashcode一定相同

hashcode相同 值不一定相同

是否可以继承String类?

String 类是final类,不可以被继承。

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的

就是说,不能传过去了,那里方法改了数据。这里方法数据也变了。

String和StringBuilder、StringBuffer的区别?

String是只读字符串,String引用的字符串内容是不能被改变的

StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改

单线程环境下使用 StringBuilder 因为它的所有方面都没有被synchronized修饰,它的效率也比StringBuffer要高

多线程使用 StringBuffer (String八佛,八。多,所以是多线程,线性安全)

String和StringBuilder、StringBuffer执行速度

String拼接,线程安全,速度最慢(10000条记录大概265毫秒)

StringBuffer拼接,线程安全,速度略快(10000条记录大概16毫秒)

StringBuilder拼接,线程不安全,速度最快(10000条记录大概0毫秒)

速度 string 《 stringBuffer 《 String builder

描述一下JVM加载class文件的原理机制?

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

类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件

Java 中会存在内存泄漏吗,请简单描述

理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露

GC是什么?为什么要有GC?

GC是垃圾收集的意思,垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存

String s = new String(“xyz”);创建了几个字符串对象?

两个对象,一个是静态区的”xyz”,一个是用new创建在堆上的对象。

接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?
接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。

Java 中的final关键字有哪些用法?

(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

数据类型之间的转换:
- 如何将字符串转换为基本数据类型?
- 如何将基本数据类型转换为字符串?

调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型

一种方法是将基本数据类型与空字符串(”")连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf()方法返回相应字符串

try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?

会执行,在方法返回调用者前执行。

有两种情况

1、finally内没有return

return-〉finally-〉try中的return

2、finally内有return

return-〉finally-〉finally中的return

详细看https://blog.csdn.net/qq_32786139/article/details/103182962

列出一些你常见的运行时异常?

- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)

- SecurityException (安全异常)

List、Set、Map是否继承自Collection接口?

List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

Collection和Collections的区别?

Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

List、Map、Set三个接口存取元素时,各有什么特点?

List以特定索引来存取元素,可以有重复元素。

Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。

Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。对象锁依旧保持

wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。放弃对象锁 并且需要 notify 或者 notifyall来唤醒

线程的sleep()方法和yield()方法有什么区别?

优先级问题

sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;

yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

执行后状态

线程执行sleep()方法后转入阻塞(blocked)状态,

而执行yield()方法后转入就绪(ready)状态;

异常

sleep()方法声明抛出InterruptedException,

而yield()方法没有声明任何异常;

可移植性

sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?

不能

其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

请说出与线程同步以及线程调度相关的方法。

- wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
- sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常
- notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
- notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

编写多线程程序有几种实现方式?

共三种

继承Thread类

实现Runnable接口

这两种都要通过重写run()方法来定义线程的行为,

推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。

还有一种是 实现Callable接口,重写call函数

synchronized关键字的用法?

synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。

同步和异步。

阻塞和非阻塞

简述synchronized 和java.util.concurrent.locks.Lock的异同?

相同点:

Lock 能完成synchronized所实现的所有功能

不同点:

Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。

synchronized会自动释放锁,

而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)

事务的ACID是指什么?

- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
- 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

获得一个类的类对象有哪些方式?

- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:”hello”.getClass()

- 方法3:Class.forName(),例如:Class.forName(“java.lang.String”)

Collections.sort排序内部原理

在Java 6中Arrays.sort()和Collections.sort()使用的是MergeSort

在Java 7中,内部实现换成了TimSort,其对对象间比较的实现要求更加严格

hashMap原理,java8做的改变

HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全。ConcurrentHashMap线程安全。

解决碰撞:

当出现冲突时,运用拉链法,将关键词为同义词的结点链接在一个单链表中,散列表长m,则定义一个由m个头指针组成的指针数组T,地址为i的结点插入以T(i)为头指针的单链表中。Java8中,冲突的元素超过限制(8),用红黑树替换链表。

HashMap 与 Hashtable 的区别

Hashtable继承Dictonary类, HashMap继承自abstractMap

HashMap允许空的键值对, 但最多只有一个空对象,而HashTable不允许。

HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。

Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。

 

HashMap内部维护了一个存储数据的Entry数组,HashMap采用链表解决冲突

ArrayList与 LinkedList 的区别?

ArrrayList 底层的数据结构是数组,支持随机访问

LinkedList 的底层数据结构书链表,不支持随机访问。使用下标访问一个元素

ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。LinkedList是双向链表

从时间复杂度也可以看出。ArrrayList的查询速度是要比LinkedList快的

新增删除操作。由于ArrayList底层是数组。如果想在数组中添加一条数据。如果不是在最后位置添加,那么就需要将它位置后的所有数据向后移一位。删除则向前加一位。

LinkedList由于是双向链表。在新增删除操作是只需要将前后指向的地址改一下就可以了。

由上也可以看出。ArrayList只需要存储数据。而LinkedList需要存储数据,还有前后指向地址。所以LinkedList所需的存储空间是比ArrayList要高的

单向链表和双向链表的区别

双向链表的话他需要存储的是前面的数据地址,和后面的数据地址。这样的话。你访问任何一个数据,都可以访问到他前-后的数据,

单向链表存储的是他后面的数据地址。所以,只能向后访问。无法访问到前面的数据。

Comparator 与Comparable 有什么不同?

Comparable 接口用于定义对象的自然顺序,是排序接口

comparator 通常用于定义用户定制的顺序,是比较接口。我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

Java中多态的实现原理

所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。

如何创建单例模式?说了双重检查,他说不是线程安全的。如何高效的创建一个线程安全的单例?

一种是通过枚举,一种是通过静态内部类。

最好的单例模式是枚举 枚举 enum 基本用法 以及 实现最佳单例模式

poll() 方法和 remove() 方法的区别?

poll() 和remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

JVM分为哪些区,每一个区干吗的?

1)方法区(method):被所有的线程共享。方法区包含所有的类信息和静态变量。

2)堆(heap):被所有的线程共享,存放对象实例以及数组,Java堆是GC的主要区域。

3)栈(stack):每个线程包含一个栈区,栈中保存一些局部变量等。

4)程序计数器:是当前线程执行的字节码的行指示器。

进程与线程

进程值运行中的程序(独立性,动态性,并发性),线程指进程中的顺序执行流。区别是:1.进程间不共享内存 2.创建进程进行资源分配的代价要大得多,所以多线程在高并发环境中效率高。

序列化与反序列化

序列化指将java对象转化为字节序列,反序列化相反。主要是为了java线程间通讯,实现对象传递。只有实现了Serializable或Externalizable接口类对象才可被序列化。

产生死锁的四个条件

.互斥条件(进程独占资源)

请求与保持(进程因请求资源而阻塞时,对已获得的资源保持不放)

不剥夺条件(进程已获得的资源,在末使用完之前,不能强行剥夺)

循环等待(若干进程之间形成一种头尾相接的循环等待资源关系)

线程同步与阻塞的关系?同步一定阻塞吗?阻塞一定同步吗?

线程同步与否 跟 阻塞非阻塞没关系,同步是个过程,阻塞是线程的一种状态

多个线程操作共享变量时可能会出现竞争。这时需要同步来防止两个以上的线程同时进入临界区内,在这个过程中后进入临界区的线程将阻塞,等待先进入的线程走出临界区。

javac命令和java命令做什么事情呢

java是分两部分的:一个是编译,一个是运行。

javac:负责的是编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译。 生成了jvm可以识别的字节码文件。也就是class文件,也就是java的运行程序。

java:负责运行的部分.会启动jvm.加载运行时所需的类库,并对class文件进行执行.一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main函数.

& 和 &&区别

& :无论左边结果是什么,右边都参与运算。

&&:短路与,如果左边为false,那么右边不参数与运算。

| 和|| 区别

 |:两边都运算。

||:短路或,如果左边为true,那么右边不参与运算。

构造函数

用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种。

特点:

该函数的名称和所在类的名称相同。

不需要定义返回值类型。

该函数没有具体的返回值。

所有对象创建时,都需要初始化才可以使用。

父子类 静态代码块、代码块、构造方法的执行顺序

父类静态代码块-〉子类静态代码块-〉父类代码块-〉父类构造方法-〉子类代码块-〉子类构造方法

详情看...

static

特点

想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。

被静态修饰的成员,可以直接被类名所调用。

静态随着类的加载而加载。而且优先于对象存在。

弊端

有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。

静态方法只能访问静态成员,不可以访问非静态成员。因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。

静态方法中不能使用this,super关键字。因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。

主函数是静态的。

break 和 continue;

两个不能一起用,一起用下面的那个会报错

break 是 结束循环。也就是不再继续执行接下来的循环了。

continue 则是 结束本次循环,接下来的循环还会继续。

==和equals方法究竟有什么区别

==:   判断两个字符串在内存中首地址是否相同,即判断两者是否是同一个字符串对象

equles():如果没有重写equals()方法比较的是对象的地址,因为对Object来说对象没有什么属性可以比较,只能比较最底层的地址.

而如果重写equals()方法时,该方法的对象因为是Object的子类,所以调用时会调用子类对象里面的方法.所以只有重写equals()方法后,两者比较的才是内容.或者说重写可以使自己定义比较的规则,不想按照地址去比较.

int和integer的区别

int 属于基本数据类型。初始值为 0,只能用  == 来比较

integer属于封装类,初始值为null,可以用eques来比较

这样的话。integer 就可以区分 0和null

取整有关的方法

Math.ceil():表示向上取整;Math.ceil(11.3)=12;Math.ceil(-11.3)=-12。

Math.floor():表示向下取整;Math.floor(11.6)=11;Math.floor(-11.6)=-12。

Math.round():表示四舍五入;Math.round(11.5)=12;Math.round(-11.5)=-11;

Math.round(11.3)=11;Math.round(-11.3)=-11;

待更新...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值