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. android-------- 强引用、软引用、弱引用、虚引用使用

    在Java中,虽然不需要程序员手动去管理对象的生命周期,但是如果希望某些对象具备一定的生命周期的话(比如内存不足时JVM就会自动回收某些对象从而避免OutOfMemory的错误)就需要用到软引用和弱引 ...

  2. 02linux 基本命令

    系统环境变量的设置 以nginx为例: 方式一: ~/.bash_profile  这是个人的 /etc/profile 为系统的环境变量 vim /etc/profile.d/nginx.sh #在 ...

  3. linux网络配置命令(二)——ip

    ip命令 查看/设置路由.设备.路由策略和渠道信息 格式 ip [ OPTIONS ] OBJECT { COMMAND | help } OBJECT := { link | addr | addr ...

  4. Python特点

    用一种方法,最好只用一种方法来做一件事 1.面向对象(解决一个问题,先考虑由“谁”来做,怎么做是“谁”的职责) 函数.模块.数字.字符串都是对象 在Python中一切皆对象 完全支持继承.重载.多重继 ...

  5. DP 租用游艇

    洛谷P1359租用游艇 分析:这个游艇我看到题目下意识的就想将dp数组设为dp[i][j]表示i到j之间的最短距离,但题目上要求的只是从起点到终点的距离,这样设只是自找麻烦. 直接设成dp[i]表示从 ...

  6. poj2891 扩展中国剩余定理

    求a1x1+r1=y...anxn+rn=y,crt合并 //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optim ...

  7. 文件名简体转繁体bat

    @echo off rem 指定文件夹路径 set "fd=D:\下载的图片" rem 0为转换文件名,1为转换文件夹名,2为同时转换文件名和文件夹名 set f=0 rem 0为 ...

  8. shiro身份验证

    身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...

  9. poj-2369-置换

    Permutations We remind that the permutation of some final set is a one-to-one mapping of the set ont ...

  10. 解决gitHub下载速度慢的问题

    转载:http://blog.csdn.net/x_studying/article/details/72588324 github被某个CDN被伟大的墙屏蔽所致. 解决方法: 1.访问http:// ...