JavaEE面试题总结
一、基础语法与算法
1. a++ 与 ++a的区别?
a++: 后置自增,先计算表达式的值,变量值后+1
++a: 前置自增,变量值先+1,再计算表达式的值
2. &和&&的区别
&有两个用法:
- 第一个是作为逻辑运算符使用,被当成逻辑运算符时有一个非短路的特性,即当第一个操作数为false,那么第二个操作数仍然执行。
- 第二个是作为位运算符使用。
&&只有一个用法:
- 只能作为逻辑运算符使用,和&的区别在于&&有一个短路的特点,即当第一个操作数为false时(因为这个时候已经可以确定表达式的最终结果已经是false),那么第二个操作数不会执行。
3. 说说jvm
jvm: java虚拟机,
用法1:可以将字节码解释成不同平台都能识别的指令
用法2:在jvm中的垃圾回收机制,可以自动回收系统中的无用内存
4. GC是什么? 为什么要有GC?
GC为垃圾回收器,系统中开辟了大量空间,当这些空间无用时,可通过GC进行释放;提高系统执行性能
5. 数组有没有length()这个方法?String有没有length()这个方法?
数组没有length()方法,只有length属性;
String有length()方法;
二、面向对象
1. 什么是多态?
概念:
多态是面向对象的基本特征之一。在java中一个对象的类型可以分为两种,即编译时类型与运行时类型。当一个对象的编译时类型和运行时类型不相同的时候,就发生了所谓的多态。
理解:
换句话说,在Java中用一个父类(父接口)的变量指向之类的对象时,就发生了多态。比如 A a = new B(), 其中A是B的父类或者父接口。为什么会有这样的特性?为什么不是子类的变量指向父类的对象?我们可以换一个生活中的例子来理解。比如现在想要一个动物,先声明一个动物的变量:
Animal a;
但是在实际生活中,根本没有一个具体的物种叫动物,所以其实我们需要创建的一个具体的动物的对象,比如狗(动物是狗的父类):
new Dog();
最后将一条狗给与正需要一个动物的‘你’是一个非常合理的行为:
Animal a = new Dog();
反过来却不成立,同样也不合理,你没办法把随便一个动物给一个正需要狗的人。
作用:
多态在面向对象编程中有着非常重要的作用。很多架构搭建,设计模式都使用到了多态的特性。多态的最大作用在于,使用一个父类的变量调用方法时,本质上调用的是子类的重写方法。换而言之,让一个Animal a执行 '叫喊'的行为,本质上我们听到的应该是“旺、旺、旺”,因为这个动物其实是Dog。这个特点让多态广泛的运用在架构与程序设计之中,极大的增强了程序的拓展性与维护性。
2. Integer封装类可以被继承吗?
不能,因为它是final修饰的类。
sun在设计Integer类时添加了final关键字,意为不让其他人随意的拓展和覆盖Integer本来的行为方法。这么设计的作用在于Integer是int类型的包装类,是对基本类型在面向对象的一个补充,很多基础类和第三方的工具类大量引用了这个类型的变量。如果随意覆盖本来的方法会导致这些基础类无法达到预想的结果,从而破坏了底层的实现效果(比如破坏了自动装箱和自动拆箱)。这是sun公司不愿意看到的。如果要对Integer有任何拓展,完全可以通过自定义一个类对Integer进行封装来实现,无需继承。
3. String可以被继承吗?
不能,同上
4. int 和 Integer有什么区别?
int为基本类型,Integer为引用类型。
Integer是int类型的包装类,对于int类型在面向对象中的补充。在很多时候没办法直接使用int基本类型,这个时候就需要用到Integer了,比如泛型时,是不能填写基本类型的,必须使用包装类。另外在很多实体类的设计时,通常也是使用包装类,因为包装类可以直接复制为null,而基本类型必须根据不同的基本类型赋予不同的值,操作起来会更加麻烦。
5. extends和implements区别
implements: 用于实现一个接口
extends: 用于继承一个类
注意:当一个接口需要继承另一个接口时,需要用到extends关键字,而且接口继承多个接口。
6.构造器Constructor是否可被override?
构造器Constructor不能被继承,因此不能重写,但可以被重载。
7. 接口是否可以继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?抽象类中是否可以有静态的main方法?
- 接口可以继承接口,而且接口继承多个接口
- 抽象类可以实现接口
- 抽象类可以继承具体类
- 抽象类中可以有静态main方法
8. 类的加载机制
8.1. 什么是类加载机制?
在一个java程序运行时,虚拟机并不会立刻将这个程序所有的类信息加载到内存中,而是在这个类第一次被使用时进行加载。将一个类加载到虚拟机内存中的过程称为类加载机制。
注意:一个类在一条JVM进程中只会被加载一次。
8.2. 类加载的步骤
类加载可以大致分成3个步骤,分别是:
-
声明静态Field时指定初始值;
-
使用静态初始化块为静态Field指定初始值;
-
验证:验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
-
准备:准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值
-
解析:
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。 -
通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明一定要从一个Class文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等,不同的渠道可以使用不同的类加载器);
-
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
-
在堆内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
-
加载阶段
在加载阶段需要用到类加载器(ClassLoader类),虚拟机需要完成以下3件事情: -
连接阶段
连接阶段和加载阶段是交叉进行的,可能加载阶段还没有完成,连接阶段已经开始,但是加载和连接的开始顺序是固定不变的。连接阶段又可以拆分成3个阶段: -
初始化阶段
在类的初始化阶段,JVM负责对类进行初始化,主要是对静态Field初始化。
对静态Field初始化分两种:初始化顺序会按照源码的编写顺序执行。
8.3. 类的加载的时机
当碰到以下几种情况时会触发一个类被加载进虚拟机内存中:
- 创建类的实例。(new关键字、反射、反序列化等等)
- 访问类中的某个静态成员
- 使用反射方式强制创建某个类对应的Class对象。比如:Class.forName("包名.类名");
- 加载某个类的子类
- 直接使用java.exe命令运行某个主类,当运行某个主类时,程序会先加载该主类
8.4. (类加载机制)据下方代码,写出打印结果:
public class SSClass
{
static
{
System.out.println("SSClass");
}
}
public class SuperClass extends SSClass
{
static
{
System.out.println("SuperClass init!");
}
public static int value = 123;
public SuperClass()
{
System.out.println("init SuperClass");
}
}
public class SubClass extends SuperClass
{
static
{
System.out.println("SubClass init");
}
static int a;
public SubClass()
{
System.out.println("init SubClass");
}
}
public class NotInitialization
{
public static void main(String[] args)
{
System.out.println(SubClass.value);
}
}
结果:
SSClass
SuperClass init!
123
原因:
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
8.5. (类加载机制)查看如下代码,写出打印结果:
package jvm.classload;
public class StaticTest
{
public static void main(String[] args)
{
staticFunction();
}
static StaticTest st = new StaticTest();
static
{
System.out.println("1");
}
{
System.out.println("2");
}
StaticTest()
{
System.out.println("3");
System.out.println("a="+a+",b="+b);
}
public static void staticFunction(){
System.out.println("4");
}
int a=110;
static int b =112;
}
结果:
2
3
a=110,b=0
1
4
9. 请简述面向对象的一些基本概念
- 封装:将类的属性私有化,使用方法进行封装来获取设置和获取属性值
- 继承:子类继承父类,可使用父类的属性和方法; 另一大特性:重写
- 多态:父类对象指向子类对象,可以调用子类重写方法
- 抽象:如果一个类有相关方法不知具体实现,该方法可设置为抽象方法,所在类就是抽象类;
具体实现交给子类完成;在应用中抽象类可作为模板使用
10. java中的常用类,不少于6个?
String,StringBuffer,Date,SimpleDateFormat,Random,Math,System,Runtime等
网友评论