每周10道Java面试题~第二期
1️⃣ 数据在计算机底层是如何存储的?存储的基本单位是什么?
现今使用的计算机系统基本上是二进制系统,其 数据在计算机中主要是以二进制补码的形式存储。二进制作为计算机技术中广泛采用的一种数制,用0和1两个数码即可表示所有数字。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。
计算机进行数据存储的基本单位是“字节” (Byte) 简写为B,常用的单位还有KB、MB、GB、TB等等。一般计算机在同一时间内处理的一组二进制数称为一个计算机的“字”,而这组二进制数的位数就是“字长”,常以位(bit)表示,并且是8的整数倍(1 Byte = 8位)。因此,可以发现有8位机、16位机、32位机、64位机等不同系统,代表了不同的读写处理能力。
2️⃣ 变量的定义要注意哪些问题?
(1)明确正确的变量类型。变量可以是基本类型(byte、short、int、long、float、double、char、boolean)或引用类型(对象、数组)。定义变量时需要明确其正确的类型,特别的定义long类型的变量时,需要在整数后面加上L(大小写均可);定义float类型的变量时,需要在小数后面加上F(大小写均可);
(2)变量命名应当具有意义,即变量名应该能够准确地表达变量的用途或值的意思;
(3)遵循命名约定,变量名应遵循驼峰命名法;
(4)变量是存在作用域(类变量变量、实例变量、局部变量)的,在同一作用域内不能出现同名变量;
(5)变量在使用之前,必须赋上初始值。
3️⃣ 成员变量和局部变量的区别?
变量定义时,根据变量所在的代码块范围分为成员变量(也叫实例变量或对象变量)和局部变量两种。
成员变量指定义在类中方法外的变量,局部变量则是定义在方法体或代码块内部的变量。
成员变量和局部变量的主要区别在于作用域和生命周期不同。成员变量拥有更长的生命周期和更广泛的作用域,而局部变量的生命周期和作用域均限定在其声明的代码块内或方法调用过程中。
具体区别细节如下:
- 从语法形式上看,成员变量是属于类或对象的,而局部变量是在方法中定义的变量或方法参数;
- 从修饰符上看,成员变量可以被 权限修饰符等其他关键字所修饰,而局部变量不能被权限修饰符及static所修饰,但二者都能被final所修饰;
- 从变量在内存中的存储方式及生命周期来看,成员变量是对象的一部分:被static修饰的成员变量也叫类变量,存储于方法区当中,生命周期与当前类相同;未被static修饰的成员变量也叫实例变量,存储于对象所在的堆内存当中,生命周期与对象相同。而局部变量存储于栈内存中,其生命周期随方法的调用结束而结束,变量空间会自动的释放;
- 从初始值上看,成员变量若未被赋初值,则会自动以对应数据类型的默认值来赋值(一种情况例外:被final修饰但没有被static修饰的成员变量,必须显式地赋值)。而局部变量则不会自动赋初值;
- 从使用范围上看, 局部变量只能在声明它的方法或代码块内使用,不能被其他方法或代码块访问。
4️⃣ 值传递和引用传递是指什么?
值传递是对基本类型数据变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
引用传递一般是对于引用数据类型变量而言的,传递的是该对象地址的一个副本,并不是原对象本身。
值传递是指将参数的值直接传递给函数,函数对这个参数的修改不会影响到原来的值。也就是说,在函数内部可以改变这个参数的值,但是不会影响到函数外部这个参数的值。
引用传递是指将参数的引用(内存地址)传递给函数,函数对这个参数的修改会影响到原来的值。也就是说,在函数内部修改这个参数的值,会影响到函数外部这个参数的值。
一般认为,Java的基础数据类型传递都是值传递,而实例对象等引用类型的传递是引用传递。
5️⃣ 自动类型转换与强制类型转换是指什么?
自动类型转换指在运算中,数据类型范围小的变量可以直接赋值给数据类型范围更大的变量。
最终运算结果的数据类型由表达式中的最大范围数据类型决定。
自动类型转换规则如下:byte或short或char -> int -> long -> float -> double。
强制类型转换是指可以强行将类型范围大的变量或者数据赋值给类型范围小的变量。
但要注意,强制类型转换可能造成数据(丢失)溢出;浮点型强转成整型,是直接丢弃小数部分,只保留整数部分。
// 自动类型转换
int a = 5;
char b = 'A';
int c = a + b;
System.out.println(c); //70. char类型自动转换为了int类型
// 强制类型转换:数据类型 变量名 = (数据类型)变量名或数据;
long a = 135L;
byte b = (long)a;
System.out.println(b); //-121. 因为超出了byte类型的取值范围,造成了数据溢出
6️⃣ 构造方法与普通方法的区别是什么?
普通方法代表对象的行为。可以有修饰符修饰、返回值。方法名不能和类名相同。
构造方法目的是给对象实例变量赋值。不能被static、final、synchronized、abstract和native修饰,无返回值。方法名必须和类名保持一致。
普通类/抽象类中至少有一个构造方法(默认会有一个空的构造方法),可以有任意多个普通方法;
接口中不能有构造方法,可以有任意多个default修饰的普通方法。
7️⃣ 自增\自减运算符(“++”\“–”)前置和后置使用的区别?
++ 是自增运算符,会让变量自身的值做 + 1操作。
当 ++在前(即前置)时: 先自增,再做其他操作;当 ++在后(即后置)时: 先做其他操作,再自增。
int a=1;
int c = ++a;
System.out.println("c=" + c + ", a=" + a);//c=2, a=2
int d = a++;
System.out.println("d=" + d + ", a=" + a);//d=2, a=3
– 是自减运算符,会让变量自身的值做 - 1操作。
当 --在前(即前置): 先自减,再做其他操作;当 --在后(即后置): 先做其他操作,再自减。
int a=8;
int e = --a;
System.out.println("e=" + e + ", a=" + a);//e=7, a=7
int f = a--;
System.out.println("f=" + f + ", a=" + a);//f=7, a=6
8️⃣ static方法如何调用?有什么需要注意的点?
static关键字修饰的方法是静态方法,静态方法可以在不创建类的对象的情况下直接调用,使方法和对象解绑。格式:类名.方法名()。需要注意的是:
(1)静态方法中只能访问用static 修饰的成员(静态成员),无法访问非静态成员,因其需要创建对象才能访问;
(2)静态方法也可以用 实例名.方法名() 来访问,只是在实现底层,仍然会被转为 类名.方法名()。
9️⃣ static关键字的作用?
static关键字主要用于创建独立于具体对象的类变量或方法(也即 静态变量或静态方法),这样一来即使没有创建对象也可以直接通过类使用变量或方法(如类名.静态方法)。
static还可以用来形成静态代码块 以优化程序性能或做一些初始化操作,因为static代码块只会在类加载的时候执行一次。
需要注意的是,static方法只能被继承不能被重写。
🔟 final关键字的作用?
final关键字的特征就是凡是被 final修饰的地方都不能修改。
- final修饰类,表示该类不能被继承;
- final修饰方法,表示该方法不能被重写;
- final修饰变量:若是基本数据类型,表示该变量值不能被更改;若修饰的是形式参数,表示一旦被赋值则不能更改。若是引用数据类型,例如修饰对象时,引用在初始化后将永远地指向一个内存地址,不可修改,但是内存地址中保存的对象内容是可以修改的。