前言

最近无聊的在逛某 tube 网站,本来想看看大家是怎么吐槽川普的,结果无意间点进了一个老外面试 Java 的视频,对于常年面试被吊打的我瑟瑟发抖,于是决定进去一探究竟。

毕竟不是专业的后台开发,所以我在面试到后台知识的时候果断的退了出来,才让自己免受了侮辱

不过鉴于我手速出众,飞速的记录下了 Java 的基础题,所以准备贡献出来,供大家享乐。

鉴于题目比较多,会分成上下 2 篇 来整理,主要是面对 Java 的基础,看看老外的面试题和我们有什么区别。

当然问题是老外问的,答案是我编的。

正文

Java 中有哪些可用的分配内存

Java 虚拟机在执行程序时候会将内存划分为不同的数据区域

  • 方法区 - Method Area

    • 方法区(Method Area)与 Java 堆一样,是所有线程共享的内存区域
    • 虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫 Non-Heap(非堆),目的应该是与 Java 堆区分开。
    • 运行时常量池(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类的版本/字段/方法/接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将类在加载后进入方法区的运行时常量池中存放。运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的是 String.intern() 方法。受方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 异常。
    • 方法区的大小和堆空间一样,可以选择固定大小也可选择可扩展,方法区的大小决定了系统可以放多少个类,如果系统类太多,会导致方法区溢出虚拟机同样会抛出内存溢出错误
    • JVM 关闭后方法区即被释放
  • 堆 - Heap Area
    • 对于大多数应用,Java 堆是 Java 虚拟机管理的内存中最大的一块,被所有线程共享。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数据都在这里分配内存。
    • Java 虚拟机规范规定,Java 堆可以是处于物理上不连续的内存空间中,只要逻辑上是连续的即可,像磁盘空间一样。实现时,既可以是固定大小,也可以是可扩展的,主流虚拟机都是可扩展的(通过 -Xmx-Xms 控制),如果堆中没有完成实例分配,并且堆无法再扩展时,就会抛出 OutOfMemoryError 异常。
  • 栈 - Stack Area
    • 栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器
    • JVM 直接对虚拟机栈的操作只有两个:每个方法执行,伴随着入栈(进栈/压栈),方法执行结束出栈
    • 栈不存在垃圾回收问题
  • 程序计数器 - Program Counter Register
    • 它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域
    • 在 JVM 规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期一致
    • 任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。如果当前线程正在执行的是 Java 方法,程序计数器记录的是 JVM 字节码指令地址,如果是执行 native 方法,则是未指定值(undefined)
    • 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
    • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
    • 它是唯一一个在 JVM 规范中没有规定任何 OutOfMemoryError 情况的区域
  • 本地方法栈 - Native Method Stack Area
    • Java 虚拟机栈用于管理 Java 方法的调用,而本地方法栈用于管理本地方法的调用
    • 本地方法栈也是线程私有
    • 允许线程固定或者可动态扩展的内存大小
      • 如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java 虚拟机将会抛出一个 StackOverflowError 异常
      • 如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么 Java虚拟机将会抛出一个 OutofMemoryError 异常
    • 它的具体做法是 Mative Method Stack 中登记 native 方法,在 Execution Engine 执行时加载本地方法库当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。它和虚拟机拥有同样的权限。
    • 并不是所有 JVM 都支持本地方法。因为 Java 虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等。如果 JVM 产品不打算支持 native 方法,也可以无需实现本地方法栈
    • 在 Hotspot JVM 中,直接将本地方法栈和虚拟机栈合二为一

如果我写 static public void main,程序还会运行吗?

刚看到这个题目的时候懵逼了,在国内面试真没见过这么问的,所以还是有些不确定,所以赶紧搜索。

在 Java 中的修饰符出现在字段声明中时的顺序与 oracle 规定的 FieldModifier 顺序一致,这是习惯顺序,形成规范。不遵守这个约定没有技术影响,但是会降低代码的可读性,因为大多数开发人员都习惯于标准顺序。

所以程序变成 static public void main() 也可以运行。

下面仅列举方法修饰符:

局部变量中的默认值是什么?

在 Java 中的局部变量不会初始化。

public class staticFactory {
public static void main(String[] args) {
int temp;
System.out.println(temp);
}
}
// 打印信息:Error:(10, 28) java: 可能尚未初始化变量 temp

如果是静态变量不赋值,会直接默认值为 0

public class staticFactory {
static int temp;
public static void main(String[] args) {
System.out.println(temp);
}
}
// 打印值为 0

如果是成员变量

public class staticFactory {
public static void main(String[] args) {
LocalVariables obj = new LocalVariables();
System.out.println("a="+obj.a);
System.out.println("b="+obj.b);
System.out.println("c="+obj.c);
System.out.println("d="+obj.d);
}
}
class LocalVariables {
int a;
char b;
float c;
String d;
}
/*
打印结果:
a=0 int 默认值为 0
b="" char 默认值为 ""
c=0.0 float 默认值为 0.0
d=null String 默认值为 null
*/

在 Java 中如何拷贝构造函数

Java 中的拷贝构造方法是一种使用该类的一个对象构造另外一个对象的构造方法。

如何创造拷贝构造方法

// 要创建拷贝构造方法,首先需要声明带有和本类相同类型的参数构造函数:
public class Employee {
private int id;
private String name; public Employee(Employee employee) { }
}
// 然后,将参数对象的每个属性都复制给新的实例。
public class Employee {
private int id;
private String name; public Employee(Employee employee) {
this.id = employee.id;
this.name = employee.name;
}
}

上面的做法属于浅拷贝。

上面定义的属性是基本类型和不可变类型 (int 和 String),因此使用前拷贝就没问题。

但是如果类中包含可变类型就要通过该构造函数实现深拷贝

为了实现深拷贝,我们需要根据原始可变对象类型构造新的实例。

public class Employee {
private int id;
private String name;
private Date startDate; public Employee(Employee employee) {
this.id = employee.id;
this.name = employee.name;
this.startDate = new Date(employee.startDate.getTime());
}
}

什么是标记接口

标记接口是没有任何方法和属性的接口,它仅仅表明它的类属于一个特定类型,供其他代码测试允许做一些事情。并且标记接口不是 Java 这门语言特有的,而是计算机科学中的一种通用化的设计理念。

使用标记接口的唯一目的是使得可以用 instanceof 进行类型查询,例如:

if (obj instanceof Cloneable) {………}

在 Java 中,有一个常用的标记接口类

  • java.io.Serializable:未实现此接口的类将无法使其任何状态序列化或反序列化。为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。
  • java.lang.Cloneable:表明 Object.clone() 方法可以合法地对该类实例进行按字段复制。实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。
  • java.util.RandomAccess:用来表明其支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。
  • java.rmi.Remote:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。

为什么 Java 不完全面向对象

首先什么才是纯面向对象语言?

纯面向对象语言或完全面向对象语言是指完全面向对象的语言,它支持或具有将程序内的所有内容视为对象的功能。它不支持原始数据类型(如 int,char,float,bool 等)。编程语言满足七种标准可以就可以称为纯粹的面向对象语言,他们是:

  1. 封装 / 数据隐藏
  2. 继承
  3. 多态性
  4. 抽象化
  5. 所有预定义类型都是对象
  6. 所有用户定义的类型都是对象
  7. 对对象执行的所有操作必须仅通过对象公开的方法

为什么 Java 不是纯面向对象语言?

Java 支持属性 1、2、3、4 和 6 但不支持上面给出的 5 和 7。 Java 语言不是纯面向对象语言,因为它包含以下属性:

原始数据类型例如对象:

Smalltalk 是一种 “纯粹的” 面向对象的编程语言,与 Java 和 C++ 不同,因为作为对象的值和作为基本类型的值之间没有区别。在 Smalltalk 中,原始值,例如整数,布尔值和字符也是对象。在 Java 中,我们将预定义类型作为非对象 (基本类型)。

int a = 5;
System.out.print(a);

static 关键字:

当我们将一个类声明为 static 时,可以在不使用 Java 中的对象的情况下使用它。

以上两点可以解释为什么 Java 不是完全面向对象。

你能在 Java 程序中实现指针吗

Java 虚拟机隐式地负责内存管理。Java 的主要格言是保持编程简单。因此,不建议直接通过指针访问内存。所以,指针在 Java 中被消除了,Java 中并没有指针

解释一下 Java String 池

在 Java 的堆内存空间中,有一块区域用来存放 Java 字符串池。当需要创建一个新的字符串的时候,JVM 首先检查对象是否存在于字符串池中,如果存在,这个引用的对象将指向该变量,如果不存在则创建一个新对象。

由于String实例对象不可修改,因此,“多个 String 实例对象引用变量引用同一个 String 实例对象”在节省 Java 堆内存的情况下,并不会带来任何问题。

直接赋值的方式

使用 new 的方式

  • 此时,如果判断 S1 == S2 是否相等是返回 true 的,因为他们指向同一个值
  • 如果判断 S3 == S4 是否相等返回 false,因为他们比较的是 S3 和 S4 的地址

当 main() 方法没有生命成静态会发生什么?

main() 方法是 Java 程序的入口,也可以理解为一个接口,在 java 编程中,JVM 会查找类中的 public static void main ( String [] args ),如果找不到该方法就抛出错误 NoSuchMethodError:main 程序终止。main() 方法必须严格遵循它的语法规则,方法签名必须是 public static void,参数是字符串数组类型。

当然还有其他一些意义:

  • 正因为 main() 方法是静态的,JVM 调用这个方法就不需要创建任何包含这个 main() 方法的实例。
  • 因为 C 和 C++ 同样有类似的 main() 方法作为程序执行的入口。
  • 如果 main() 方法不声明为静态的,JVM 就必须创建 main() 类的实例,因为构造器可以被重载,JVM 就没法确定调用哪个 main() 方法。
  • 静态方法和静态数据加载到内存就可以直接调用而不需要像实例方法一样创建实例后才能调用,如果 main() 方法是静态的,那么它就会被加载到 JVM 上下文中成为可执行的方法

总结

以上可以看的出来,老外的面试的偏向性和我们还是有些区别的,这些题有一半在我们的面试中是不常问到的,所以取长补短。

你见过老外的 Java 面试题吗 (上)?的更多相关文章

  1. java面试题全集(上)

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  2. 发一些Java面试题,上海尚学堂Java学员面试遇到的真题,值得学习

    1. 下面哪些是Thread类的方法() A start()       B run()       C exit()       D getPriority() 答案:ABD 解析:看Java AP ...

  3. 年底了,该跳槽了,全套高级Java面试题及答案整理~

    又到年底了,又是一轮跳槽季 城外的人想进去,城里的人想出来 为什么离职? 马云说过,要么工资低,要么受了委屈 我想大多数人离职是这个原因 出来混的,跳槽也都是为了更好的生活 干技术的,工资都是跳出来的 ...

  4. Java笔试题解答和部分面试题

    面试类  银行类的问题 问题一:在多线程环境中使用HashMap会有什么问题?在什么情况下使用get()方法会产生无限循环? HashMap本身没有什么问题,有没有问题取决于你是如何使用它的.比如,你 ...

  5. 尚学堂Java面试题整理

    博客分类: 经典分享   1. super()与this()的差别? - 6 -  2. 作用域public,protected,private,以及不写时的差别? - 6 -  3. 编程输出例如以 ...

  6. 金三银四季来了!Java 面试题大放送,能答对70%就去BATJTMD试试~

    摘要: 2019,相对往年我们会发现今年猎头电话少了,大部分企业年终奖缩水,加薪幅度也不如往年,选择好offer就要趁早,现在开始准备吧,刷一波Java面试题,能回答70%就去BATJTMD大胆试试~ ...

  7. 20 几个知名公司的 Java 面试题汇总

    查看不同公司新鲜真实的Java面试题,摘自Glassdoor.com 巴克莱投资: 假设有一个 getNextparson() 方法返回 Person 对象,Person 类实现了 comparabl ...

  8. 《OD面试》Java面试题整理

    一.面试考察点 1 主语言本身 2 数据库 3 算法 4 Spring/SpringMVC/MyBatis 5 项目经验 1)项目涉及到的技术点深挖: (1)考察候选人技术深度  (2)看候选人遇到问 ...

  9. Java面试题汇总---升级版(附答案)

    前几天写了Java面试题汇总---基础版,总结了面试中常见的问题及答案,那我今天基于昨天的话题做一次升级,也就是说,求职者除了要学习了解哪些常见的基础面试题之外,还得准备些什么呢? 对有工作经验的求职 ...

  10. 挑战10个最难的Java面试题(附答案)【上】【华为云技术分享】

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/devcloud/article/deta ...

随机推荐

  1. thinkphp 3.2.3 动态修改conf配置文件

    thinkphp 3.2.3 的C()方法能修改配置文件,但是是动态修改的,没有真正的更改文件. 我查了网上网友分享的方法,都不怎么合适,我就自己摸索写了一个,配置写到text.php中,我的目录如下 ...

  2. PBOC2.0协议中电子存折/电子钱包中圈存交易流程

    通过圈存交易,持卡人可将其在银行相应账户上的资金划入电子存折或电子钱包中.这种交易必须在金融终端上联机进行并要求提交个人识别码(PIN)(无论电子存折还是电子钱包应用). 交易流程图如下: 1.1 发 ...

  3. hdu acm 1028 数字拆分Ignatius and the Princess III

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  4. oracle每天清理归档日志

    http://langzhiwang888.iteye.com/blog/1675033 参考这里的内容 在数据库服务器上新建一个bat文件(文件名随意) 编辑此文件为: rman target 's ...

  5. HashMap两种遍历数据的方式

    HashMap的遍历有两种方式,一种是entrySet的方式,另外一种是keySet的方式. 第一种利用entrySet的方式: Map map = new HashMap(); Iterator i ...

  6. BZOJ1103 [POI2007]大都市meg(DFS序)

    题目:一颗树,单边修改,链上查询..实际上链是根到结点的链.网上好像有其他做法,我的想法是这样的: 先不看修改,毫无疑问查询只是查询结点的深度:而修改一条边会有什么影响:影响是且只是以边上深度最深结点 ...

  7. HW4.17

    import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...

  8. android禁用光感按键

    用RE浏览器打开/system/usr/keylayout下的qwerty.kl文件, 找到key 158 BACK key 139 MENU key 102 HOME 分别在其之前加下#号,如下: ...

  9. nstallation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED报这个错的原因???

    [2015-06-05 20:37:51 - 05ListView列表控件] ------------------------------ [2015-06-05 20:37:51 - 05ListV ...

  10. 漫谈Java IO之普通IO流与BIO服务器

    今天来复习一下基础IO,也就是最普通的IO. 网络IO的基本知识与概念 普通IO以及BIO服务器 NIO的使用与服务器Hello world Netty的使用与服务器Hello world 输入流与输 ...