Java面试题(每天10题)---连载

1、ArrayList和linkedList的区别

Array (数组)是基于索引 (index) 的数据结构,它使用索引在数组中搜索和读取数据是很快的。
Array 获取数据的时间复杂度是 O(1), 但是要删除数据却是开销很大,因为这需要重排数组中的所有数据  (因为删除数据以后 , 需要把后面所有的数据前移 )
缺点 : 数组初始化必须指定初始化的长度 , 否则报错
例如:
int[] a = new int[4];//推介使用int[] 这种方式初始化
int c[] = {23,43,56,78};//长度:4,索引范围:[0,3]
List— 是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式,它继承 Collection
List 有两个重要的实现类: ArrayList LinkedList
ArrayList: 可以看作是能够自动增长容量的数组
ArrayList toArray 方法返回一个数组
ArrayList asList 方法返回一个列表
ArrayList底层的实现是Array, 数组扩容实现
LinkList 是一个双链表 , 在添加和删除元素时具有比 ArrayList 更好的性能 . 但在 get set 方面弱于
ArrayList. 当然 , 这些对比都是指数据量很大或者操作很频繁。

 2、HashMap和HashTable的区别

(1) 、两者父类不同
HashMap 是继承自 AbstractMap 类,而 Hashtable 是继承自 Dictionary 类。不过它们都实现了同时实现了map Cloneable (可复制)、 Serializable (可序列化)这三个接口。
(2) 、对外提供的接口不同
Hashtable HashMap 多提供了 elments() contains() 两个方法。
elments() 方法继承自 Hashtable 的父类 Dictionnary elements() 方法用于返回此 Hashtable 中的
value 的枚举。
contains() 方法判断该 Hashtable 是否包含传入的 value 。它的作用与 containsValue() 一致。事实上,contansValue() 就只是调用了一下 contains() 方法。
(3) 、对 null 的支持不同
Hashtable key value 都不能为 null
HashMap key 可以为 null ,但是这样的 key 只能有一个,因为必须保证 key 的唯一性;可以有多个 key值对应的value null。
(4) 、安全性不同
HashMap 是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,因此需要开发人员自己 处理多线程的安全问题。
Hashtable 是线程安全的,它的每个方法上都有 synchronized 关键字,因此可直接用于多线程中。
虽然 HashMap 是线程不安全的,但是它的效率远远高于 Hashtable ,这样设计是合理的,因为大部分的,使用场景都是单线程。当需要多线程操作的时候可以使用线程安全ConcurrentHashMap
ConcurrentHashMap 虽然也是线程安全的,但是它的效率比 Hashtable 要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。
(5) 、初始容量大小和每次扩充容量大小不同
(6) 、计算 hash 值的方法不同

3、Collection包结构,与Collections的区别

Collection 是集合类的上级接口,子接口有Set、List、LinkedList、ArrayList、Vector、Stack、Set;

Collections 是一个帮助类,包含各种有关集合操作的静态方法,用于实现对各种集合的搜索、排序、线程安全化等操作。此类不能实例化,就像一个工具类,服务与Java的Collection框架。

 4、Java的四种引用

  • 强引用

强引用是平常使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:

String str = new String("str")
  •  软引用

软引用在程序内存不足的时候,会被回收,使用方式:

// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的,
// 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));

可用场景:创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。

  • 弱引用

弱引用就是只要JVM垃圾回收器发现了,就会被回收,使用方式:

WeakReference<String> wrf = new WeakReference<String>(str);

 可用场景:Java源码中的java.util.weakHashMap中的key就是使用的弱引用,我的理解就是,一旦我不需要某个引用,JVM会自动帮我处理它。

  • 虚引用
虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。注意
哦,其它引用是被 JVM 回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用
大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue ,使用例子:
PhantomReference<String> prf = new PhantomReference<String>(new
String("str"), new ReferenceQueue<>());
可用场景: 对象销毁前的一些操作,比如说资源释放等。 ** Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效。
上诉所说的几类引用,都是指对象本身的引用,而不是指 的四个子类的引用 (softReference )

5、泛型常用特点

泛型是Java SE 1.5 之后的特性,《Java核心技术》中对泛型的定义是:

“泛型”意味着编写的代码可以被不同类型的对象所重用。

我们提供了泛型的概念,但是具体执行的时候却可以有具体的规划来约束,比如ArrayList就是个泛型类,ArrayList作为集合可以存放各种元素,但在我们使用的时候通过具体的规则来约束。

使用泛型的好处:

以集合来举例,使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合,如整型集 合类,浮点型集合类,字符串集合类,我们可以定义一个集合来存放整型、浮点型,字符串型数据,而这并不是最重要的,因为我们只要把底层存储设置了Object 即可,添加的数据全部都可向上转型为Object。 更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。

6、Java创建对象有几种方式

Java中提供了以下四种创建对象的方式:

  • new创建新对象
  • 通过反射机制
  • 采用clone机制
  • 通过序列化机制

7、有没有可能两个不相同的对象有相同的hashcode

有可能。在产生hash冲突时,两个不相等的对象就会有相同的hashcode值,当hash冲突产生时,一般有以下几个方式可以处理:

  • 拉链法:每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,呗分配到同一个索引上的多个节点可以用这个单向链表进行存储。
  • 开放地址法:一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
  • 再哈希:又被称为双哈希法,有多个不同的Hash函数。当发生冲突是,使用第二个,第三个...等哈希函数计算地址,直到冲突被解决。

8、深拷贝和浅拷贝的区别是什么

  • 浅拷贝: 被复制对象的所有变量都含有与原来的对象相同的值, 而所有的对其他对象的引用仍然指向原来的对象。 换言之, 浅拷贝仅仅复制所考虑的对象, 而不复制它所引用的对象。
  • 深拷贝: 被复制对象的所有变量都含有与原来的对象相同的值, 而那些引用其他对象的变量将指向被复制过的新对象, 而不再是原有的那些被引用的对象。 换言之, 深拷贝把要复制的对象所引用的对象都复制了一遍。

9、final的用法有哪些 

 final也是很多面试喜欢问的地方,但我觉得这个问题很无聊,通常能回答下以下5点就不错了:

  • final修饰的类不可以被继承
  • final修饰的方法不可以被重写
  • final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.
  • final修饰的方法,JVM会尝试将其内联,以提高运行效率
  • final修饰的常量,在编译阶段会存入常量池中.

除此之外,编译器对fifinal域要遵守的两个重排序规则更好:

在构造函数内对一个 fifinal 域的写入, 与随后把这个被构造对象的引用赋值给一个引用变量, 这两个操作之间不能重排序;
初次读一个包含 fifinal 域的对象的引用 , 与随后初次读这个 fifinal , 这两个操作之间不能重排序。
import static java.lang.Math.*;

public class Test {
    public static void main(String[] args) {
//System.out.println(Math.sin(20));传统做法
        System.out.println(sin(20));
    }
}

10、static都有哪些用法

所有的人都知道 static 关键字这两个基本的用法: 静态变量和静态方法, 也就是被 static 所修饰的变量 / 方法都属于类的静态资源, 类实例所共享。
除了静态变量和静态方法之外 ,static 也用于静态块 , 多用于初始化操作:
public calss PreCache{
  static{
//执行相关操作
  }
}
此外 static 也多用于修饰内部类 , 此时称之为静态内部类。
最后一种用法就是静态导包, import static .import static 是在 JDK 1.5 之后引入的新特性, 可以用来指定导入某个类中的静态资源, 并且不需要使用类名 , 可以直接使用资源名, 比如:
import ststic java.lang.Math.*;

public class Test {
    public static void main(String[] args) {
//System.out.println(Math.sin(20));传统做法
        System.out.println(sin(20));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头的Tomcat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值