<Java><!!!><面试题>
装箱 & 拆箱
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
}
对于上述代码:
- s == s1,很好理解,因为他俩都是字符串常量,指向常量池中的同一块空间;
- s1 != s2, 因为s2是在堆中new出来的一块内存
- s1 == s5,因为s5也是字符串常量,编译时被确定,仍然与s1指向同一块常量池空间;
- 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><!!!><面试题>的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- http bass
1.http 是超文本传输协议,是从万维网服务器传输超文本到本地浏览器的传输协议 2.http是一个基于tcp/ip通信协议来传输数据(html,图片,查询结果等) 3.一个完整的http请求包含7个 ...
- node模块之net模块——socket
当我们去面试的时候,常常会遇到这样一个问题:当用户在浏览器地址栏输入一段url发出资源请求后,到服务端返回数据呈现给用户的这个过程都发生了什么? 我们把进行通信的这两个端(这里指的是,浏览器和资源获取 ...
- python-day71--django多表双下划线查询及分组聚合及F/Q查询
#====================================双下划线的跨表查询===============# 前提 此时 related_name=bookList 属性查询: # 查 ...
- leetcode-algorithms-34 Find First and Last Position of Element in Sorted Array
leetcode-algorithms-34 Find First and Last Position of Element in Sorted Array Given an array of int ...
- WDA基础六:字段,表等visiable,enable,read_only控制
今天主要讲一下布局控制:(visiable,enable,read_only) visiable:可见性,控制字段,组件,分组等是否现实在界面上.一般按条件来控制隐藏的可以在CONTEXT NODE里 ...
- 解决VS Code保存时候自动格式化
VS code 保存会自动格式化.以前都是alt+shift+F格式化的,现在一保存就格式化 解决方式:找到你的VScode扩展,把JS-CS-HTML Formatter这个插件禁用就可以解决
- dubbo 自定义 Filter
通过自定义 Filter,可以在 dubbo 调用链中加入特定的逻辑,比如埋点分析调用链. 1. 新建 Filter 类 // @Activate(group = {Constants.CONSUME ...
- 在springboot中验证表单信息(六)
构建工程 创建一个springboot工程,由于用到了 web .thymeleaf.validator.el,引入相应的起步依赖和依赖,代码清单如下: 1 2 3 4 5 6 7 8 9 10 11 ...
- PHP配置方法
由于php是一个zip文件(非install版),安装较为简单,解压就行.把解压的 php5.2.1-Win32重命名为 php5.并复制到C盘目录下.即安装路径为 c:\php5 1 找到php目录 ...
- Redis分布式锁实例
maven依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</ ...