1. Java是解释性的语言吗?
答: java程序的源代码是解释性的,但.java文件要通过2个步骤才能变成机器语言:
1)在java平台上被编译成字节码(bytecode)的.class形式,这是二进制的JVM的机器语言。
2)JVM附带解释器,对这些字节码解释执行。
PS:Java的.class文件可以在任何平台上JVM运行!反之,离开了JVM的环境,.class的二进制字节码无法适用于任何平台。
PS2:在JDK-11的JRE支持cmd下直接用java xx.java直接运行java文件,不需要javac编译再运行
2. 为什么说Java有分布式的特点
答:java支持Internet应用开发,包含java.net接口,提供了许多web开发的类库,包括URL,URLConnection,Socket,ServerSocket等等。还有Java RMI支持远程调用Java对象方法。这样可以在对等的两端激活远程方法,这也可以发生在客户端和服务器之间。这些都是分布式应用开发的有利工具。
3.UML是啥?类型分为几类?
UML就是统一建模语言,分为静态,动态和物理图。
静态图Static Diagram,描述不发生任何变化的软件元素的逻辑结构。描绘类,对象,数据结构及其中关系。
…
4. 为什么要用内部类,非静态内部类为什么成员变量不能有static?
答: 外部类只能继承一次父类,然而内部类提供了继承的多重实现!
非静态内部类的成员变量初始化,就如同非静态方法与成员变量一样,依赖于外部类的实例化。JVM分配内存时,static类,方法以及成员变量优先分配,然而内部类的static成员变量缺少实例化的内部类无法分配内存。
5. 手动实现枚举类需要满足哪些特点?
答: 枚举类的实现有3个特点:
1) 所有的实例要用public static final来修饰并作为成员属性保存,实例名大写+下划线组成
2) 构造器用private隐藏
3) 提供一些static方法来供其他程序访问实例。
6. 枚举类enum的实例化呢,哪些特点?
答: 1)enum和class interface平级,enum继承的是Enum类
2)所有实例必须放根大括号{}内第一行,用逗号分隔,名称大写
3)enum构造器private隐藏
4)enum类无法被继承,也没被继承的意义
5)enum类占用内存是手动枚举类的2倍以上,对Android编程敏感
7. 面向对象的特征有哪些方面
1)抽象
抽象就是忽略当前与目标无关的方面,不打算了解全部,只取其部分特征。
抽象用于过程抽象与数据抽象。
数据抽象针对对象属性,比如鸟有翅膀,脚,羽毛。
过程抽象针对对象行为,比如鸟会飞。
2)继承
继承就是子类能够继承超类的特征和行为,即超类的方法与实例变量能够被继承。
3)封装
封装数据与操作数据的方法,限制未经过授权的访问操作数据。
4)多态性
多态性是抽象与继承的实现,包含函数与运算符的重载。前者参数多态,后者强制或隐式转换。
还有一种是包含的多态,即同一操作同时用于子类型与父类。
8.String和StringBuffer区别
String长度不变,Stringbuffer可变。
而且Stringbuffer支持多线程,即线程安全,链接字符串使用Append就行。
String不支持线程,且每次+的过程中生产对象。
9. 运行时的异常与一般异常异同?
异常表示程序运行过程中可能出现非正常状态,运行时异常表示虚拟机操作中可能的异常。Java编译器要求申明抛出可能发生的非运行时异常,但不要求必须声明抛出未被捕获的运行时异常。但是并不要求必须声明抛出未被捕获的运行时异常。
10. Java 虚拟机模型
Java虚拟机运行时的数据分为6种:
1.程序计数器:是一个数据结构,用于保存当前正常执行的程序内存地址。Java虚拟机的多线程通过线程轮流切换并分配处理器时间来实现的,为了线程切换后能恢复到正确的位置,每条线程需要一个独立的程序计数器,也就是该区域线程私有。
- Java虚拟机栈:线程私有的,与线程生命周期相同,用于存储局部变量表,操作栈,方法返回值。局部变量表放着基本数据,操作栈,方法返回值。局部变量放着基本数据类型,还有对象的引用。
- 本地方法栈:跟虚拟机栈很像,使用native方法
- Java堆: 所有线程共享一块内存区域,对象实例几乎都在这分配内存。
- 方法区:各线程共享的区域,储存虚拟机加载类的信息,常量,静态变量,编译后的代码。
- 运行时常量池:代表运行时每个class文件中的常量表。包括几种常量,方法或者域的引用
11. 多态好处
允许不同类的对象对同一消息做出响应,即同一消息可以根据发送对象的不同采取不同的行为方式(发送消息就是函数调用)。有以下优点:
- 可替换性:多态对已存在代码具有可替换性
- 可扩充性:增加新的子类不影响已经存在的类结构
- 接口性: 多态是超类通过方法签名,向子类提供一个公共平台接口,由子类来完善或者重写方法。
12. 代码中如何实现多态
实现多态主要有以下三种方式:
- 接口实现
- 继承父类的重写方法
- 同一类中进行方法重载
13. 接口意义
接口的意义用三个词:规范,扩展,回调。
14. 抽象类的意义
- 为其他子类提供一个公共的类型
- 封装子类中重复定义的内容
15. 父类的静态方法能否被子类重写
不能。重写只适用于实例方法,子类中含有父类相同签名的静态方法叫做隐藏。
16. 什么是不可变对象
不可变对象指被创建后状态不能改变,任何修改都会创建一个新的对象。 如String与包装类
17. 静态变量和实例变量的区别
静态变量存储在方法区,属于类所有。实例变量存储在堆当中,其引用存在当前线程栈。
18. 能否创建一个包含可变对象的不可变对象
当然可以,但是不要共享对象的引用,如果需要变化时,就返回对象的一个拷贝。最常见的例子就是对象中包含一个日期对象的引用。
19. Java 创建对象的几种方式
- 采用new
- 反射
- clone
- 序列化
前两者需要显示调用构造函数。耦合第一种最严重,无论任何框架,解耦都需要减少new
20. switch 能否作用在byte,long上
可以用于byte但是不能用于long
21. String s1=“ab”,String s2=“a”+“b”,String s3 = “a”, String s4 = “b”, String s5 = s3 + s4 请问s5 == s2返回什么?
返回false;
编译中,编译器会将s2直接优化为“ab”,将其放在常量池里,换而言之,s1==s2返回true!
s5是一个新的对象,创建在堆。
22. Object的公共方法?
- equals()
- clone()
- getClass()
- notify(),notifyAll(),wait()
- toString()
23. 说说&和&&的区别
&& 是 逻辑运算符中的与,即两边表达式皆为true,结果才为true
& 和&&的区别在于,&会计算两边表达式,&&只要一边表达式为false则停止计算另一边表达式
&在两边表达式不为&时会进行按位与计算,结果转换为比如 0x0 & 0x1 结果为0
24. 在JAVA中如何跳出当前的多重嵌套循环?
在java代码体中,我们用break跳出当前循环体,如果想要跳出多重,
那么只要在想要跳出的循环体前和break后加标号即可。
25.switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
switch (expr1){ case expr2: action; }语句中的参数只支持int,String,enum
但是byte,short,char都可以隐式转换为int,故byte可以,long不可以
26. String、StringBuffer、StringBuilder的区别
(1)可变与不可变:String是不可变字符串对象,StringBuilder和StringBuffer是可变字符串对象(其内部的字符数组长度可变)。
(2)是否多线程安全:String中的对象是不可变的,也就可以理解为常量,显然线程安全。StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是StringBuffer 中的方法大都采用了synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是非线程安全的。
(3)String、StringBuilder、StringBuffer三者的执行效率:
StringBuilder > StringBuffer > String 当然这个是相对的,不一定在所有情况下都是这样。比如String str = “hello”+ "world"的效率就比 StringBuilder st = new StringBuilder().append(“hello”).append(“world”)要高。因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:
当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;
当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。
27.说说final的用法
final是一个修饰符,在修饰不同对象时发挥的作用不同
- final修饰的数据只能进行一次赋值操作,对于基本变量,变量赋值后不可更改。对于引用变量,引用的对象的地址不可改,但是引用对象的属性是可以修改的。
- final修饰方法参数时,被传入的变量的值或者引用对象(地址)在方法体内是不可更改的。
- final修饰方法时,表示该方法无法覆盖,即不能被Override
- final修饰类时,类不能被继承
28. 描述下int a = 1;在类中申明和方法中申明赋值区别
1)在类中,基本类型a申明是成员变量,随着类的实例化存于堆中,所在地址存放1这个字面量的值。
2)在方法中,基本类型a申明是局部变量,随着方法运行存于栈中,所在地址存放1这个字面量的值。
29. 描述下Integer a = 1在类中和方法中申明赋值的区别
Integer a = 1 是自动装箱,等于 Integer a = Integer.valueOf(1)。
该静态方法返回一个(在堆中缓存数组里的)Integer(1)实例。
无论在类中还是方法中,引用类型a赋值后即引用Integer(1)这个对象地址。
区别在于:
1)在类中,引用类a是成员变量,申明时存在堆中
2)在方法中,引用类a是局部变量,申明时存在栈中
30. 描述下JVM运行class文件时方法区的作用?
方法区存储类型(class,interface,enum,annotation)信息:
1) 完整有效名 (包名.类名)
2)直接父类的完整有效名(Object除外)
3)类型修饰符 (public,final,abstract)
4)类直接接口的有序列表
5)常量池 (每个类用到的字面量集合,包括字符串,整数,浮点数,以及符号引用)
6) 域信息 (名称,类型,修饰符)
7)方法信息 (名称,返回类型,参数表,修饰符)
8)静态变量
注意: 方法区仅仅是JVM的逻辑存储区,物理上属于堆内存,在Java 8后由Metaspace实现,又叫做非堆。metaspace详细参考https://www.cnblogs.com/yulei126/p/6777323.html
31. 说说JVM的内存分配机制
- 首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。
JVM内存分配分为 堆内存和非堆内存:
堆内存:
- JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC后调整堆的大小。
非堆内存:
- VM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。