Java基础(上):
-
Java特点:平台无关性(JVM)、面向对象、内存管理(Java有自己的内存回收机制,自动管理内存和回收不再使用的对象)
- JavaSE vs JavaEE:JavaSE(Java平台标准版)、JavaEE(Java平台企业版)
- JVM vs JDK vs JRE:JVM(运行Java字节码的虚拟机,将字节码.class编译或解释为机器码)
- Java为什么跨平台?Java跨平台是因为JVM能够将字节码编译或解释为特定的机器码,使得Java程序能在不同的平台上运行。
- 什么是字节码?JVM可以理解的代码就叫字节码(扩展名为.class文件)
- Java程序变为机器码的过程:Java源代码 à Javac进行编译 à.class文件(字节码文件)à JVM解释为机器码 à 执行 à执行结果
- JIT(运行时编译):由于原先的JVM类加载器首先加载字节码文件,再通过解释器逐行执行逐行解释,效率较低 à在执行时,JIT会把翻译过的机器码保存下来,以备下次使用
- Java源程序被编译成.class文件后打成jar包或war包,部署过程中通过Java虚拟机加载应用程序然后解释
- 为什么说Java语言编译与解释共存?因为Java源代码经过编译变成.class文件,再经过解释变成机器码,具有两个步骤。
- 高级编程语言分为两种:1.编译型(编译型语言会通过编译器将源代码一次性翻译成机器码,执行速度快,开发效率低):C、C++ 2.解释型(解释型语言会通过解释器一句一句将代码解释为机器代码后再执行)Python
- Oracle JDK和Open JDK的区别:1.不开源vs开源 2.部分版本免费vs免费 3.功能稍微多一点vs功能少一点 4.稳定性差不多
- Java和C++的区别:1.都面向对象 2.Java类是单继承(只能继承一个父类),接口是多继承 3.Java具有自动内存管理、垃圾回收机制
- Java三种注释方式:1.单行 2.多行 3.文档注释:Java开发文档 (编译器在编译之前把代码中的注释抹掉)
- 标识符和关键字:特殊标识符就是关键字 !!true、false、null是标识符
同一个类中 | 同一个包中 | 不同包的子类 | 不同包的无关类 | |
public | P | P | P | P |
protected | P | P | P | |
无 | P | P | ||
private | P |
- 自增自减运算符
- 移位运算符(被操作的数据被视为二进制数):Java中三种移位运算符:1. <<:左移位运算符,向左移若干位,高位丢弃,低位补0 2. >>:右移运算符,向右移若干位,高位补符号位,低位丢弃。正数补0,负数补1。 3. >>>:无符号右移,忽略符号位,全都补0。
为什么使用移位运算符?1.高效:直接对应于处理器的移位指令 2.性能优化:可以使用移位代替乘法或除法 3.进行权限管理和状态标记
- continue、break、return的区别是什么? continue:跳出这次循环,执行下一次循环 break:跳出整个循环体,执行循环下面的语句 return:结束当前方法
- Java基本数据类型(8种):
4种整数类型:byte、short、int、long
2种浮点数类型:float、double
1种字符类型:char
1种布尔类型:boolean
基本类型 | 位数 | 字节 |
byte | 8 | 1 |
short | 16 | 2 |
int | 32 | 4 |
long | 64 | 8 |
char | 16 | 2 |
float | 32 | 4 |
double | 64 | 8 |
boolean | 1 |
- 基本类型和包装类的区别?
用途?存储方式?(栈内存vs堆内存)占用空间?默认值?比较方式?
注意:基本数据类型存放在栈中是一个常见的误区!基本数据类型的存储位置取决于它们的作用域和声明方式。如果它们是局部变量,那么它们会存放在栈中;如果它们是成员变量,那么它们会存放在堆中。
- 包装类型的缓存机制了解么?
Java基本类型的包装类基本都用到了缓存机制。
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。减少内存的使用,提高性能。
- 什么是自动拆装箱?
装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;
- 为什么浮点数运算的时候会有精度丢失的风险?
这个和计算机保存浮点数的机制有很大关系。我们知道计算机是二进制的,而且计算机在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就会导致小数精度发生损失的情况。这也就是解释了为什么浮点数没有办法用二进制精确表示。
- 如何解决浮点数运算的精度丢失问题?
BigDecimal 可以实现对浮点数的运算,不会造成精度丢失。因为BigDecimal用完整的十进制字符串来表示和存储数据。
- 超过long整型的数据应该如何表示?
基本数值类型都有一个表达范围,超出这个范围就会有数值溢出的风险。
- 成员变量与局部变量的区别?
语法形式、存储方式(没有static修饰存储在堆内存,局部变量存储在栈内存中)、生存时间、默认值
- 为什么成员变量有默认值?
成员变量是类的属性,属于对象,在类中定义,在对象创建时分配内存。当对象被创建时,内存系统会为对象分配空间,并把这些空间清零,也就是系统为成员变量赋了一个默认值。
而局部变量的使用在编译期是可以完全检查的。如果程序中的某个局部变量在使用前没有被初始化,编译器就会报错。避免了不必要的内存初始化,提高了效率。
- 静态变量(static修饰的变量)有什么作用?
它可以被类的所有实例共享,无论一个类创建了多少个对象,它们都共享同一份静态变量。也就是说,静态变量只会被分配一次内存,即使创建多个对象,这样可以节省内存。
静态变量会被 final 关键字修饰成为常量。
- 字符型常量和字符串常量的区别?形式、含义、占内存大小
- 方法
方法的返回值是指我们获取到的方法体执行结束后产生的结果
- 静态方法为什么不能调用非静态成员?
- 静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
- 在类的非静态成员不存在的时候静态方法就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。
类加载(Class Loading):
- 在 Java 中,当程序首次使用某个类时(比如调用类的静态方法或创建该类的对象),JVM 会将该类加载到内存中。这时,JVM 会给类的静态成员(方法和变量)分配内存,并为其初始化。
- 类加载的时机通常是在第一次引用该类时,比如调用静态方法、访问静态变量、或者创建对象。
- 对象实例化(Object Instantiation):
- 对象实例化是通过new关键字来创建类的对象。每创建一个对象,JVM 会为该对象的非静态成员分配内存。
- 每个对象都有自己独立的非静态成员,即使多个对象来自同一个类,它们的非静态变量的值也可以不同。
- 静态方法与实例化方法有何不同?
1.调用方式(调用静态方法无需创建对象)
2.访问类成员是否存在限制(静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制)
- 重载(编译期)和重写(运行期)有什么区别?
- 重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理
- 重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法。
- 重载
- 发生在同一个类中(或者父类和子类之间),方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。如果多个方法(比如 StringBuilder 的构造方法)有相同的名字、不同的参数, 便产生了重载。
- 重写
- 发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
- 方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
- 如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
- 构造方法无法被重写
- 什么是可变长参数?
- 可变长参数就是允许在调用方法时传入不定长度的参数。就比如下面这个方法就可以接受 0 个或者多个参数。(String ... args)
- 可变参数只能作为函数的最后一个参数,但其前面可以有也可以没有任何其他参数。
- 遇到方法重载的情况怎么办呢?会优先匹配固定参数还是可变参数的方法呢?
- 答案是会优先匹配固定参数的方法,因为固定参数的方法匹配度更高。