1. 装箱 & 拆箱

public class Test03 {

    public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
}

这个题有几个知识点要明确:1)上面4个变量都是object,所以 == 比较的不是值,而是引用。2)要清楚装箱的本质:我们给一个Integer赋int值的时候,会调用Integer类的静态方法valueOf,该方法的源码如下:

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

其中IntegerCache是Integer的内部类,如果整形字面量的值在-128 ~ 127之间,那么就不会new新的Integer对象,而是直接引用常量池中的Integer对象。

综上,答案是 true & false。

  2. 内存中的栈、堆和方法区的用法(JVM)

通常我们定义一个基本数据类型的变量,一个对象的引用,以及函数调用的现场都保存在JVM的栈中。而通过new关键字和构造器创建的对象则放在堆中。

堆是垃圾收集器管理的主要区域由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为From Survivor和To Survivor)、Tenured。

    • 堆、栈、方法区的区别:

      • 栈由系统自动分配释放,使用一级缓存,它们通常是被调用时处于存储空间,调用完毕立即释放;每个线程都有一个栈区,只保存基础数据类型和对象的引用。栈分为三个部分:基本类型变量区、执行环境上下文、操作指令区。
      • 堆由程序员分配释放,使用二级缓存,生命周期由虚拟机的垃圾回收算法来决定。jvm只有一个堆区,被所有线程共享,堆中只存放对象本身。
      • 方法区又叫静态区,也被所有线程共享。方法区包含所有的class和static变量。

以上,栈空间操作起来最快,但是栈很小,通常大量对象都是放在堆空间,栈和堆的大小都可以通过JVM启动参数来调整。栈用完会引发StackOverflowError,而堆和常量池空间不足会引发OutOfMemoryError。

String str = new String("hello");

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

  3. 用最有效率的方法计算2乘以8? 
  答: 2 << 3。在HashCode()的源码中,hashCode的公式是 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] ,为什么这里要使用31?这里有两个考虑:

    • 31是素数(质数),使用素数可以降低冲突概率;
    • 31 * num 等价于(num << 5) - num,左移5位相当于乘以2的5次方再减去自身就相当于乘以31,现在的VM都能自动完成这个优化。

  4. equals & hashCode

  两个对象值相同(x.equals(y) == true), 那它们可能有不同hash code吗?

  答:不能。Java规定,若两个对象相同(equals返回true),那么它们的hashCode一定相同。但是相反不一定成立。

  当然,你未必一定按要求去做,但是如果你违背了上述原则就会发现使用在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(hashCode频繁冲突造成的存取性能急剧下降)。

  关于equals方法:必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。

  5. 如何实现对象克隆

  有两种方式:

  1)实现Cloneable接口并重写Object类中的clone()方法;

  2)实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。[implements Serializable接口,实现toString()方法]

  6. GC

  Java提供的gc功能可以自动监测对象是否超过作用域,从而达到自动回收内存的目的。可以通过System.gc()或Runtime().gc()请求垃圾收集,但是JVM可以屏蔽掉显式地垃圾回收调用。

  垃圾回收通常作为一个低优先级的线程运行。垃圾回收机制有很多种,包括分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:

  • - 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
  • - 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
  • - 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。

  7. Java类加载机制

class A {

    static {
System.out.print("1");
} public A() {
System.out.print("2");
}
} class B extends A{ static {
System.out.print("a");
} public B() {
System.out.print("b");
}
} public class Hello { public static void main(String[] args) {
A ab = new B();
ab = new B();
} }

上面这段代码的执行结果是1a2b2b。

类加载机制的相关知识比较多一点,专门整理了一篇博客  点我点我点我

  8. String

    private void testString(){
String s1 = "Programming";
String s = "Programming";
String s2 = new String("Programming");
System.out.println(s2.getClass().toString());
String s3 = "Program";
String s4 = "ming";
String s5 = "Program" + "ming";
String s6 = s3 + s4;
System.out.println(s1 == s); // true
System.out.println(s1 == s2); // false
System.out.println(s1 == s5); // true
System.out.println(s1 == s6); // false
}

对于上述代码:

  1. s == s1,很好理解,因为他俩都是字符串常量,指向常量池中的同一块空间;
  2. s1 != s2, 因为s2是在堆中new出来的一块内存
  3. s1 == s5,因为s5也是字符串常量,编译时被确定,仍然与s1指向同一块常量池空间;
  4. s1 != s6, 这里由于s3和s4的拼接需要额外创建一个StringBuffer(或StringBuilder),之后再将StringBuffer转换为String,此处很明显new了一个对象,因此是在堆中进行的。(最后得到的s6是StringBuilder.toString()的返回值。看了下源码,返回的是 return new String(value, 0, count);

这里有一个很重要的点,既然直接用 + ,底层也会用StringBuilder去实现,那么为什么在实际中我们通常会说用StringBuilder,而不去用 + 呢?考虑的是这样的情况:

public class Test4 {
public static void main(String[] args) {
String s = "s";
for (int i = 0; i < 20; i++) {
s += i;
}
}
}

上述代码中,用String+的方式,每循环一次,就会重新new一个StringBuffer对象,这样的内存消耗完全是不必要的(在数据量大的情况下,还会导致内存不足的错误)。# 据说字符串的加法是java唯一一个实现了运算符重载的地方。

<Java><!!!><面试题>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 关于如何获取Google 官方 NavgationView中的控件的方法

    最近在想要寻找一个好集成的SlidingMenu,看上了官方的DrawLayout,简单易集成 然后如果想动态改变DrawLayout头部的HeaderVIew的资源的话需要先获取到控件 方法如下 n ...

  2. Confluence 6 修改空间名字和标识

    希望修改空间名称: 在空间名称的边上,选择  图标. 输入新的空间名称,然后单击 保存(Save). 标识(Logo )- 修改空间的名称和标识. 重新组织(Reorder) - 拖动来从新组织快捷链 ...

  3. 用where导致group by分组字段的索引失效

    把两个单独的索引合并成一个组合索引,即把where条件字段的索引和group by的分组字段索引组合成一个. 如果分组的字段需要用函数处理,可以用索引函数 Generated Column(函数索引) ...

  4. python模块--time & datetime

    time模块 #获取当前时间的时间戳 import time >>> time.time() 1535004894.0959966 #日期字符串转化成时间戳 >>> ...

  5. Educational Codeforces Round 48 (Rated for Div. 2)G. Appropriate Team

    题意:求满足条件的(i,j)对数:\(gcd(v,a_i)=x,lcm(v,a_j)=y\) 题解:\(x|a_i,a_j|y\),\(x|y\),考虑质因子p,假设a_i中p次数为a,x中次数为b, ...

  6. 【实战问题】【2】Ambiguous mapping found. Cannot map 'xxController.Create' bean method

    正文: 启动项目时出现该报错. 原因为:在controller中url映射出现重复,@RequestMapping(value = "user/create"). 解决方案为:全局 ...

  7. 我的第一个C语言程序

    从自学开始到现在应该有块一个月了,之前一直想要写博客一直没想好要自己建博客还是找平台来写.现在想想 其实都一样,不论在哪里,都可以记录自己学习的成长记录.这是我的第一篇关于C语言学习的博客,希望这只是 ...

  8. tornado 异步

    引言 注:正文中引用的 Tornado 代码除特别说明外,都默认引用自 Tornado 4.0.1. tornado.gen 模块是一个基于 python generator 实现的异步编程接口.通过 ...

  9. PHPCMS V9完全开发介绍

    PHPCMS V9 文件目录结构: 根目录 | – api 接口文件目录 | – caches 缓存文件目录 | – configs 系统配置文件目录 | – caches_* 系统缓存目录 | – ...

  10. 命令创建Vue

    创建vue+webpack vue init webpack projectName 基础 Vue+webpack+Vux 新建文件命令 # install vue-cli npm install - ...