Java面试知识点汇总
Intro
Java三大特性
- 封装
- 继承
- 多态
Java变量
Java变量包括:局部变量和成员变量
局部变量:在方法体内声明,只能在方法体中访问,方法结束内存释放
成员变量:实例变量和静态变量(成员变量使用了static关键字)
static
- 静态变量
又称为类变量,也就是说这个变量属于类的,与类的实例无关。类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。
静态变量 static:对象级别 men.name
实例变量 没有static:实例级别 Tom.name, Tony.name, Tim.name …
静态变量在类加载的时候初始化,存储在方法区当中,不需要创建对象,直接通过“类名”来访问。
- 静态方法
静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。
- 静态语句块
静态语句块在类初始化时运行一次。
存在继承的情况下,初始化顺序为:
父类(静态变量、静态语句块)
子类(静态变量、静态语句块)
父类(实例变量、普通语句块)
父类(构造函数)
子类(实例变量、普通语句块)
子类(构造函数)
Java面向对象
override / overload
重写(override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写
- 返回值和形参都不能改变。即外壳不变,核心重写!
- 父类的成员方法只能被它的子类重写
- 声明为 final 的方法不能被重写
- 声明为 static 的方法不能被重写,但是能够被再次声明
- 构造方法不能被重写
- 子类与父类的一种多态性表现
当需要在子类中调用父类的被重写方法时,要使用 super
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
重载(overload)
重载是在一个类里面,方法名字相同,但是参数不同,返回类型也可以不同
- 被重载的方法必须改变参数列表(参数个数或类型不一样)
- 可以改变返回类型
- 可以改变访问修饰符
- 可以声明新的或更广的检查异常
- 无法以返回值类型作为重载函数的区分标准
- 一个类的多态性表现
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
多态
多态是同一个行为具有多个不同表现形式或形态的能力
多态的实现方式:
- 重写
- 接口
- 抽象类和抽象方法
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
class 父类 {
}
class 子类 extends 父类 {
}
Java不支持多继承:
Java支持多重继承:
继承的特性:
- 子类拥有父类非 private 的属性、方法
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
- 子类可以用自己的方式实现父类的方法 --> 重写override
extends & implement
extends只能继承一个类
public class Penguin extends Animal{
}
implements用于类继承接口,可以继承多个接口,变相实现多继承
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
super
对父类成员的访问,用来引用当前对象的父类
this
指向自己的引用
final
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写
抽象类
不能被实例化的类
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
public abstract class Employee{
}
和普通的类看起来没有什么不同,就是不能实例化,必须要被继承
/* 实例化是不允许的,会引发错误 */
Employee e = new Employee("George W.", "Houston, TX", 43);
通过一般的方法继承abstract类
public class Salary extends Employee
抽象方法
抽象方法只包含一个方法名,而没有方法体。抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
}
- 如果一个类包含抽象方法,那么该类必须是抽象类
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类
- 继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
封装 Encapsulation
将抽象性函式接口的实现细节部分包装、隐藏起来,防止该类的代码和数据被外部类定义的代码随机访问。
Java封装步骤
- 修改属性的可见性(private)
public class Person {
private String name;
private int age;
}
- 对每个属性值提供对外的公共访问方法 --> 对每个属性创建一对赋值取值方法
public class Person{
private String name;
private int age;
// 所有属性只有通过get set才能触及
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
// this 关键字是为了解决实例变量(private String name)和
// 局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
}
接口
抽象方法的集合,一个类通过继承接口,从而来继承接口的抽象方法。
- 接口不是类。类描述对象的属性和方法,接口是包含类要实现的方法
- 除非实现接口的类是抽象类,否则这个类要实现接口中的所有方法
- 无法被实例化
- 没有构造方法
- 接口中所有方法都是抽象方法
- 支持多继承
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
接口声明
interface Animal {
public void eat();
public void travel();
}
接口的实现
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
接口可以继承另一个接口(就像类之间的继承),接口可以多继承
public interface Football extends Sports,Event....
抽象类和接口的区别
- 接口中的类全都是抽象方法,抽象类中的方法可以有方法体(非抽象)
- 接口中的变量只能是public static final类型,抽象类可以有各种类型的变量
- 一个类可以实现多个接口,一个类只能继承一个抽象类
Java GC
内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的
GC的对象
回收没有存活的对象
两种方法判断对象是否存活:
- 引用计数:对象的引用计数属性,引用新增 计数+1,引用释放 计数-1。计数 == 0,回收对象。但无法解决对象循环引用。
- 可达性分析:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。
Java多线程
Servlet
Tomcat工作机制
1.client发送http请求至server
2.Tomcat从磁盘加载Servlet (servlet进入servlet容器)
3.解析http请求为request对象
4.转发request至相应的Servlet进行处理
5.Servlet处理request后返回response
6.Tomcat将response转化为http响应
7.tomcat返回http响应至client