文章目录
参考: 地址
Java基础
面向过程与面向对象的区别
面向过程
优点:因为不需要经常实例化类,所以性能较高。
缺点:相比面向对象,不易维护、复用和扩展。
面向对象
优点:由于三大特性(封装、继承、多态),易维护、复用和扩展。
缺点:性能比面向过程低。
JVM、JDK 和 JRE 的区别
JVM:Java虚拟机,即运行Java字节码的虚拟机
注:不同平台使用相同的字节码文件(.class文件),不同的JVM。
JDK:包含JRE所拥有的,以及编译器;用于创建和编译程序。
JRE:Java运行的环境,包括JVM,Java类库等基础构件;只能用于运行程序,不能用于创建新程序。
重写和重载的区别
重写Override:发生在多个类之间,即父子类;方法名、参数列表必须相同(父类private方法子类无法重写)。
重载Overload:发生在一个类中,方法名必须相同,参数类型、个数、顺序,返回值。访问修饰符可以不同。
面向对象三大特性
封装
封装,把对象的属性私有化,并提供一些可以被外界访问这些属性的方法;如果没必要被外界访问,则不提供方法。
继承
继承,以已经存在的类作为基础建立新的类的过程,新的类即有父类的所有非private的属性和方法,还可以定义新的数据和新的功能。
多态
多态,指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
Java中的实现:继承与接口中对方法的重写。
String、StringBuffer 和 StringBuilder 的区别
可变
String 类中使用final修饰的字符数组来保存字符串,而StringBuffer 和 StringBuilder 都是 AbstractStringBuilder 的子类,直接使用字符数组来保存字符串,无final修饰,即这两种对象是可变的。
线程
String 中的对象是不可变的,即常量,所以线程是安全的; StringBuffer 对那些操作字符串的方法加了同步锁,所以线程也是安全的; 而 StringBuilder 并没有对方法进行加锁,所以是线程不安全的。
性能
操作 String 对象时,总是创建一个新的对象,然后将引用指向新的对象; StringBuffer 直接对对象本身进行操作; 而 StringBulder 性能相比 StringBuffer 仅有一点提示,而线程却不安全。
适用场景
操作少量数据:String
单线程、大量数据:StringBuilder
多线程、大量数据:StringBuffer
自动装箱和拆箱
装箱:将基本类型用相应的引用类型包装起来。
拆箱:将包装类型转为基本数据类型。
例如:
//没有自动装箱
Integer i = new Integer(10);
//自动装箱
Integer i = 10;
//拆箱
int n = i;
接口和抽象类的区别
接口
- 变量默认是 final 类型,方法默认是 public
- 所有方法都不能有实现(静态方法可以)
- 一个类可以实现多个接口,且必须实现接口所有方法
- 不能实例化,即不能 new
抽象类
- 可以有抽象方法,也可以有已经实现了的方法
- 一个类只能继承一个抽象类,且不用实现所有方法
== 与 equals 的区别
==:
基本数据类型:比较值是否相等
引用数据类型:比较的是两个对象的内存地址是否相同
equals
两种情况:
- 比较的类没有重写equals()方法,则 equals 等价于”==“
- 比较的类重写了equals()方法,则是依据重写方法比较对象的内容
hashCode 与 equals
hashCode
- 概述
用于获取哈希码(散列码),即返回一个 int 整数; 哈希码是对象在哈希表中的索引位置,每个类都包含hashCode方法(Object) - 作用:
HashSet 中存入元素时,会先判断哈希码是由相同,如果不同则说明不是重复元素; 如果相同,则才会使用 equals 判断其内容是否相同; 这个过程就提高了执行的速度
重写equals
重写equals时必须重写hashCode的原因:
两个对象相等,其hashcode必定相同,且equals必定返回true; 但单单hashcode相同,两个对象则不一定相等; 而hashcode不同,则不会进行equals的判断,所以equals方法被重写了,则hashCode也必须被重写。
按值传递
两种参数传递方法
按值调用:方法接收的是调用者提供的值
引用调用:方法接收的是调用者提供的变量地址
Java
方法对参数调用,是按值调用的
方法得到的是参数值的一个拷贝
方法无法修改参数变量的内容
线程与进程的区别
线程:是比进程更小的执行单位,一个进程在执行时可以有多个线程共同参与,且多个线程共享同一块内存空间。
进程:程序运行的基本单位,即一次执行过程。一个进程就是一个执行中的程序,而线程则是处于一个程序之中。
常见关键字总结
final 的作用地方:变量、方法、类:
- 当final修饰一个基本数据类型的变量时,在该变量初始化过后就不能在被修改;修饰一个引用类型的变量时,则该变量在初始化后就不能指向另一个对象
- 被final修饰的类不能被继承,类中所有成员方法都被隐式地指定为final方法(所有的private方法都被隐式地指定为final方法)
- 使用场景:防止继承类修改方法的含义,即锁定方法
staitc 使用场景:
- 修饰成员(变量、方法):
被 static 修饰的成员属于静态成员,能有被该类中所有的对象共享,并且可以直接通过类名调用 - 静态代码块:
静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。 一个类中可以都多个静态代码块,但是该类不管创建多少对象,静态代码块只执行一次
static {
语句体;
}
- 静态内部类:
有static修饰符的内部类,
内部可以声明static成员变量(非静态不可以)
不可使用外部类的非静态成员变量
正常内部类的创建需要依赖外围类的创建,如:
Outer out=new Outer();//先构造外部类
Outer.Iner in=out.new Inner();//才能构造内部类
而静态内部类则不需要:
Outer.Inner i=new Outer.Inner;//相当于静态成员,直接通过类名调用
- 静态导包
用于指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法,格式:
import static ...
this
用于引用当前类的实例,可用于调用该实例的变量和方法
class A{
int temp;
void demo(){
int test = this.temp;//访问类A的当前实例的变量
this.test;//调用类A的当前实例的方法
}
void test(){}
}
super
用于从子类访问父类的变量和方法
public class A{
public int a;
public void demo(){}
}
public class B extends A{
void test(){
super.a = 1;
super.demo();
}
}
instanceof
它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
注:this、super 不能用在 static 方法中,因为 this 和 super 属于对象范畴,而 static 属于类范畴
finalize
Java技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。
它在Object类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的
Java静态代码块/构造代码块/构造函数/静态变量/成员变量
静态代码块,在类加载时即运行,而且只运行一次,并且优先于各种代码块以及构造函数运行。如果一个类中有多个静态代码块,会按照书写顺序依次执行。
构造代码块,即没有static修饰的代码块,在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。如果不实例化对象,构造代码块不会执行。如果存在多个构造代码块,则执行顺序按照代码顺序依次执行。
构造方法,不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的。
程序执行顺序:静态代码块>构造代码块>构造函数>普通代码块
父子类:
- 首先执行父类静态的内容;
- 接着执行子类的静态的内容;
- 执行父类构造代码块;
- 执行父类的构造方法;
- 执行子类构造代码块;
- 执行子类的构造方法。