本文概述
本文主要总结常见Java基础知识面试题(一)
参考
Java基础知识面试题大集合(CodeSheep)
300 Core Java Interview Questions
java中短路与、逻辑与、短路或、逻辑或
Java概述(一)
什么是Java
Java是高级的,面向对象的,健壮的,安全的编程语言,与平台无关,高性能,多线程和可移植的编程语言。 它由James Gosling于1991年6月开发。由于它提供了自己的JRE和API,因此也可以称为平台。
Java特点
简单,面向对象,可移植性,与平台无关,安全性,强大性,Architecture Neutral, 解释器(JIT),高性能,多线程,分布式,动态性
C++ VS Java
比较项 | C++ | Java |
---|---|---|
平台 | 平台相关 | 平台无关 |
主要用途 | 系统编程 | 应用程序编程,广泛用于窗口,web等 |
多继承 | 支持 | 不支持多继承,在Java中使用接口实现多继承 |
运算符重载 | 支持 | 不支持 |
指针 | 可编写指针程序 | Java内部支持指针,但不能编写相应的指针程序 |
编译器和解释器 | 仅使用编译器,将源代码转换为机器代码,C++依赖平台 | Java源代码在编译时会转换为bytecode。解释器在运行时执行此bytecode并输出。 |
JVM、JRE和JDK的关系
JVM
JVM是使计算机能够运行Java程序的虚拟机。 JVM的作用类似于运行时引擎,该引擎调用Java代码中存在的main方法。 JVM是必须在计算机系统中实现的规范。 JVM将Java代码编译为一个Bytecode,该Bytecode与机器无关,并且与本机代码接近。Java语言可以实现跨平台。
JRE
JRE代表Java Runtime Environment。它是JVM的实现。 Java运行时环境是用于开发Java应用程序的一组软件工具。它用于提供运行时环境。它是JVM的实现。它实际上存在。它包含JVM在运行时使用的一组库+其他文件
JDK
JDK是Java Development Kit的首字母缩写。这是一个软件开发环境,用于开发Java应用程序和小程序。它实际上存在。它包含JRE +开发工具。 JDK是Oracle公司发布的以下给定Java平台中的任何一个的实现:
- 标准版Java平台
- 企业版Java平台
- 微型版Java平台
关系图如下:
JVM分配多少类型的内存区域
Class: 类区域存储每个类的结构,例如运行时常量池,字段,方法数据和方法代码。
Heap:这是运行时数据区,在其中将内存分配给对象
Stack:Java堆栈存储框架。 它保存局部变量和部分结果,并在方法调用和返回中起作用。 每个线程都有一个与该线程同时创建的私有JVM堆栈。 每次调用方法时都会创建一个新框架。 当框架的方法调用完成时,该框架将被销毁。
Program Counter Register: PC(程序计数器)寄存器包含当前正在执行的Java虚拟机指令的地址。
Native Method Stack: 它包含应用程序中使用的所有本机方法。
什么是跨平台性?原理是什么
java语言编写的程序,一次编译后,可以在多个系统平台上运行。
实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。
ClassLoader
Classloader是JVM的子系统,用于加载类文件。 每当我们运行Java程序时,它都会由类加载器首先加载。 Java中有三个内置的类加载器。
- Bootstrap ClassLoader:这是第一个类加载器,它是Extension类加载器的超类。 它加载rt.jar文件,该文件包含Java Standard Edition的所有类文件,例如java.lang包类,java.net包类,java.util包类,java.io包类,java.sql包类等。
- Extension ClassLoader:这是Bootstrap的子类加载器,是System类加载器的父类加载器。 它加载$ JAVA_HOME / jre / lib / ext目录中的jar文件。
- System/Application ClassLoader:这是扩展类加载器的子类加载器。 它从类路径加载类文件。 默认情况下,classpath设置为当前目录。 您可以使用“ -cp”或“ -classpath”开关更改类路径。 也称为应用程序类加载器。
什么是Bytecode?好处?
- Bytecode: Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。
- 好处: Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
Java有哪些数据类型
- 基本数据类型:
- 整型byte, short, int, long
- 浮点类型float, double
- 数值型
- 字符型
- 布尔型
- 引用数据类型
- 类class
- 接口interface
- 数组[]
基本数据类型总结
整型 | 类型名称 | 关键字 | 占用内存 | 取值范围 | 作为成员变量的默认值 |
---|---|---|---|---|---|
整型 | 字节型 | byte | 1字节 | -2^7 ~2^7- | 0 |
整型 | 短整型 | short | 2字节 | -2^15 ~2^15-1 | 0 |
整型 | 整型 | int | 4字节 | -2^31 ~2^31-1 | 0 |
整型 | 长整型 | long | 8字节 | -2^63 ~2^63-1 | 0 |
浮点型 | 单精度浮点型 | float | 4字节 | -3.403E308~ 3.403E308 | 0F |
浮点型 | 双精度浮点型 | double | 8字节 | -1.798E308~ 1.798E308 | 0D |
字符型 | 字符型 | char | 2字节 | 表示一个字符 | ‘\u0000’ |
布尔型 | 布尔型 | boolean | 1字节 | true/false | false |
用最有效率的方法计算 2 乘以 8
2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。
float f=3.4;是否正确
不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。
#short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗
对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。
而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。
访问修饰符
在Java中,访问修饰符是关键字,用于定义方法,类或变量的访问范围。 在Java中,下面给出了四个访问说明符。
- public:定义为公共的类,方法或变量可以由任何类或方法访问。
- protected:受保护的可以通过同一包的类,此类的子类或在同一类内进行访问。
- default:默认值仅在包内可用。 默认情况下,所有类,方法和变量都属于默认范围。
- private: 只能在该类内访问定义为私有的私有类,方法或变量。
修饰符 | 当前类 | 同包 | 子类 | 其他包 |
---|---|---|---|---|
private | ✔️ | ✖️ | ✖️ | ✖️ |
default | ✔️ | ✔️ | ✖️ | ✖️ |
protected | ✔️ | ✔️ | ✔️ | ✖️ |
public | ✔️ | ✔️ | ✔️ | ✔️ |
&和&&
- &运算符有两种用法:(1)按位与;(2)逻辑与。条件1 && 条件2 ,执行过程:如果条件1成立,则继续计算条件2;如果条件1不成立,则条件2不再计算,直接返回false.
- &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。
| 和 ||
- 短路或 ||:条件1 || 条件2 ,执行过程:如果条件1成立,则条件2不再计算,直接返回true;如果条件1不成立,继续计算条件2,如果条件2成立,则返回ture,否则返回false.
- 逻辑或 | :条件1 | 条件2 ,执行过程:如果条件1成立,条件2继续计算,不论条件2是否成立,都返回true;如果条件1不成立,条件2继续计算,如果条件2成立,返回true,如果条件2不成立,返回false.
关键字final
在Java中,final 用于限制用户对其进行更新。 如果初始化最终变量,则无法更改其值。 换句话说,我们可以说最终变量一旦分配给一个值,之后就再也不能更改了。 未分配任何值的最终变量只能通过类构造函数分配。
用于修饰类、属性和方法;
- 被final修饰的类不可以被继承
- 被final修饰的方法不可以被重写
- 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的
final finally finalize区别
- final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表
示该变量是一个常量不能被重新赋值。 - finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。 - finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调
用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的
最后判断。
this 关键字
this 引用当前对象的引用变量
直接引用,this指向当前对象本身
形参与成员名字崇明,用this来区分
1
2
3
4public Student(String name, int id){
this.name = name;
this.id = id;
}引用本类的构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13class Student{
private String name;
private int id;
public Student(){}
public Student(String name){
this.name = name;
}
public Student(String name, int id){
this(name);
this,id = id;
}
}
super 关键字
super可以理解为指向自己父类对象的一个指针,而这个父类指的是离自己最近的一个父类。
直接引用父类实例变量
使用super访问父类的数据成员
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Animal{
String color="white";
}
class Dog extends Animal{
String color="black";
void printColor(){
System.out.println(color);//prints color of Dog class
System.out.println(super.color);//prints color of Animal class
}
}
class TestSuper1{
public static void main(String args[]){
Dog d=new Dog();
d.printColor();
}}1
2
3Output:
black
white调用父类方法
当子类包含和父类同样的方法时,super可以调用父类方法。换句话说方法被重写时可以调用父类方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Animal{
void eat(){System.out.println("eating...");}
}
class Dog extends Animal{
void eat(){System.out.println("eating bread...");}
void bark(){System.out.println("barking...");}
void work(){
super.eat();
bark();
}
}
class TestSuper2{
public static void main(String args[]){
Dog d=new Dog();
d.work();
}
}1
2
3Output:
eating...
barking...调用父类构造器
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Animal{
Animal(){System.out.println("animal is created");}
}
class Dog extends Animal{
Dog(){
super();
System.out.println("dog is created");
}
}
class TestSuper3{
public static void main(String args[]){
Dog d=new Dog();
}
}1
2
3Output:
animal is created
dog is created
this与super的区别
- super始终指向父类上下文,this始终指向当前类上下文
- super关键字用于初始化派生类构造函数中的基类变量,this主要用于在传递给类构造函数时区分局部变量和实例变量。
- super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
- super()和this()均需放在构造方法内第一行。
- 尽管可以用this调用一个构造器,但却不能调用两个。
- this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
- this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
- 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
static
Java中的static关键字主要用于内存管理。 我们可以将static关键字与变量,方法,块和嵌套类一起使用。 static关键字属于类,而不是类的实例。
static可以是变量,方法,块,嵌套类。
主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。
因此比较常见的static应用场景有:1、修饰成员变量 2、修饰成员方法 3、静态代码块 4、修饰类(只能修饰内部类也就是静态内部类) 5、静态导包
break ,continue ,return 的区别及作用
- break 跳出上一层循环,不再执行循环,结束当前循环
- continue 跳出本次循环,继续执行下次循环,结束正在执行的循环,进入下一个循环条件
- return 程序返回,不再执行下面的代码,结束当前方法,直接返回
构造函数
- 构造函数是类似于该方法的代码块。创建类的实例时调用它。在调用构造函数时,将在内存中分配对象的内存。每次使用new()关键字创建对象是,都会至少调用一个构造函数。如果类中没有可用的构造函数,它将调用默认构造函数,在这种情况下,Java编译器默认提供默认的构造函数
- 默认构造函数: 不接受任何值的构造函数。默认构造函数主要用于使用默认值初始化实例变量,它也可以用于执行一些有关对象创建的有用任务。如果类中没有定义构造函数,则编译器会隐式调用默认构造函数。
默认构造函数的目的是为对象分配默认值。如果类中没有构造函数,则Java编译器会隐式创建一个默认的构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Student3{
int id;
String name;
void display(){
System.out.println(id+" "+name);
}
public static void main(String args[]){
Student3 s1=new Student3();
Student3 s2=new Student3();
s1.display();
s2.display();
}
}1
2
3Output:
0 null
0 null参数化构造函数:参数化构造函数是可以使用给定值初始化实例变量的构造函数。换句话说,可以说可以接受参数的构造函数称为参数化构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Student4{
int id;
String name;
//creating a parameterized constructor
Student4(int i,String n){
id = i;
name = n;
}
//method to display the values
void display(){System.out.println(id+" "+name);}
public static void main(String args[]){
//creating objects and passing values
Student4 s1 = new Student4(111,"Karan");
Student4 s2 = new Student4(222,"Aryan");
//calling method to display the values of object
s1.display();
s2.display();
}
}1
2
3Output:
111 Karan
222 Aryan为构造函数定义了两个规则。
- 构造函数名称必须与其类名称相同
- 构造函数必须没有显式的返回类型
- Java构造函数不能是抽象的,静态的,最终的和同步的
构造函数重载
在Java中,构造函数就像方法一样,但是没有返回类型。它也可以像Java方法一样重载。
Java中的构造函数重载是一种具有多个具有不同参数列表的构造函数的技术。它们的排列方式使每个构造函数执行不同的任务。编译器通过列表中的参数数量及其类型来区分它们
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class Student5{
int id;
String name;
int age;
//creating two arg constructor
Student5(int i,String n){
id = i;
name = n;
}
//creating three arg constructor
Student5(int i,String n,int a){
id = i;
name = n;
age=a;
}
void display(){System.out.println(id+" "+name+" "+age);}
public static void main(String args[]){
Student5 s1 = new Student5(111,"Karan");
Student5 s2 = new Student5(222,"Aryan",25);
s1.display();
s2.display();
}
}1
2
3Output:
111 Karan 0
222 Aryan 25Java构造函数和方法的区别
Java构造函数 Java方法 用于初始化对象的状态 一种方法用于公开对象的行为 不得有返回类型 必须具有返回类型 被隐式调用 显示调用 如果您的类中没有任何构造函数,则Java编译器会提供默认构造函数。 该方法在任何情况下都不由编译器提供。 构造函数名称必须与类名称相同。 方法名称可以与类名称相同或不同。
构造函数是否返回任何值?
是的,它是当前的类实例,不能使用返回类型,但它会返回一个值
构造函数可以只能怪其他任务而不是初始化吗?
是的,例如对象创建,启动线程,调用方法等。您可以像在方法中执行操作一样在构造函数中执行任何操作
Java中有构造函数类吗?
是
构造器类的目的是什么
提供一个Constructor类,该类可用于获取类中构造函数的内部信息,在java.lang.reflect包中可以找到它。