面试之JAVA基础篇

1.int integer 区别

  1. Integer是int的包装类,int则是java的一种基本数据类型
  2. Integer变量必须实例化后才能使用,而int变量不需要
  3. Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
  4. Integer的默认值是null,int的默认值是0Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true

2. string stringbuffer stringbuilder 区别

操作字符串的类有:String、StringBuffer、StringBuilder。
String字符串是常量,他们的值在创建之后不能更改。
字符串的底层是一个被final修饰的数组,不能改变,是一个常量

private final byte[ ] value;

StringBuilder类,字符串缓冲区,可以提高字符串操作效率,底层也是一个数组但没被final修饰,可以改变长度

private byte[ ] value;
  1. String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
  2. StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

3. equals与==区别

  1. 当使用==比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地址值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等;而引用类型进行比较时使用的是他们的hashCode()方法的返回结果。
  2. 当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现。众所周知,任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、Integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。

4.对于多态的理解

使用多态写法,左侧的父类引用指向了右侧的子类对象

Fu zi = new zi()
zi.method();

如果调用父类子类中都有的方法则执行子类方法,如果调用父类中的特有方法则执行父类方法。
访问成员变量的两种方式:

  1. 直接通过对象名称访问成员变量 :看等号左边是谁优先用谁,没有则向上查找(因为基本变量是static final的,不能被重写),如果父类中没有则错误
  2. 间接通过成员方法访问成员变量 :如果子类没有覆盖重写父类的方法则调用父类的方法,若子类重写了父类方法则调用子类的方法
zi.showAge() ->该方法属于谁就优先用谁,没有向上找

5.重载(overload)与重写(覆盖,override)的区别

覆盖(Override)是指子类对父类方法的一种重写,只能比父类抛出更少的异常,访问权限不能比父类的小,被覆盖的方法不能是 private 的,否则只是在子类中重新定义了一个新方法。
重载(Overload)表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同。
面试官: 那么构成重载的条件有哪些?
答:参数类型不同、参数个数不同、参数顺序不同。
面试官: 函数的返回值不同可以构成重载吗?为什么?
答:不可以,因为 Java 中调用函数并不需要强制赋值。举例如下:
如下两个方法:

void f(){}
int f(){ return 1; }

只要编译器可以根据语境明确判断出语义,比如在 int x = f(); 中,那么的确可以据此区分重载方法。不过, 有时你并不关心方法的返回值,你想要的是方法调用的其他效果 (这常被称为 “为了副作用而调用” ),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:

f();

此时 Java 如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。

6.“static” 关键字是什么意思?

答:“static” 关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。
面试官:Java中是否可以覆盖(override)一个 private 或者是 static 的方法?
答:Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。
Java 中也不可以覆盖 private 的方法,因为 private 修饰的变量和方法只能在当前类中使用,如果是其他的类继承当前类是不能访问到 private 变量或方法的,当然也不能覆盖。

7.JAVA中对象初始化顺序?

不考虑静态成员的初始化,调用一个对象的构造函数时,程序先调用父类的构造函数(可以通过super关键字指定父类的构造函数,否则默认调用无参的构造函数,并且需要在子类的构造函数的第一行调用),先加载parent类在加载child类,之后静态成员变量的初始化函数和静态初始化块则按照在代码当中的顺序执行,成员变量如果没有指定值的话则赋予默认值,即基本数据类型为0或false等,对象则为null;最后调用自身构造函数。

8.ConcurrentHashMap 和 Hashtable 的区别?

答:ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,HashTable 考虑了同步的问题。但是 HashTable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 将 hash 表分为 16 个桶(默认值),诸如get,put,remove 等常用操作只锁当前需要用到的桶。
面试官:ConcurrentHashMap的具体实现知道吗?

  1. 该类包含两个静态内部类 HashEntry 和 Segment ;前者用来封装映射表的键值对,后者用来充当锁的角色;
  2. Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。

9.HashMap 的简单实现原理?

HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

10.什么时候需要重写equals()?什么时候需要重写hashCode()?

首先equals与hashcode间的关系是这样的:
1、如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同(即用equals比较返回false)
为什么必须要重写hashcode方法,其实简单的说就是为了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode确实不相同的只有equals 和 hashcode 都满足的时候才能确保是同一个对象。
当我们重写一个类的 equals 方法时就应当连同重写 hashcode 方法,并且两个方法应满足:
1:一致性,即:当两个对象 equals 比较为 true,那么 hashcode 值应当相等,反之亦然,因为当两个对象hashcode 值相等,但是 equals 比较为 false,那么在 HashMap 中会产生链表,影响查询性能。
2:成对重写,即重写 equals 就应当重写 hashcode。

你可能感兴趣的:(面试之JAVA基础篇)