第一章 java基础面试(1)

本文介绍了JAVA的基础知识,包括JAVA的特点如JVM的平台无关性、多线程支持,以及JVM、JDK和JRE的区别。讲解了字节码、JAVA与C++的区别,强调JAVA是编译与解释并存的语言。此外,还涵盖了标识符与关键字、移位运算、成员变量与局部变量、静态变量和字符串常量的差异。文章还讨论了静态方法与实例方法、重载与重写的概念,以及浮点数运算的精度问题和解决方法。最后提到了超出long数据类型的表示问题。

java特点

  1. 三大特性:封装,继承,多态
  2. JAVA虚拟机实现平台无关性
  3. 多线程:std::thread和std::async
  4. 支持网络编程

JVM,JDK,JRE

  1. JVM指JAVA虚拟机。是运行JAVA字节码的虚拟机。
    针对不同系统的实现,使得用相同的字节码,会给出相同的结果。
    HotSpot VM 仅仅是是 JVM 规范的一种实现
  2. JDK是功能齐全的JAVA SDK。全称: Java 语言的软件开发工具包。有JRE的所有,+编译器和工具(javac+javadoc,jdb),能够创建和编译程序。
  3. JRE是JAVA运行时环境。运行已编译JAVA程序的所有内容的集合。包括JAVA虚拟机,java类库,java命令和其他基础构件。不能用于创建新程序

字节码

JVM是java虚拟机,JVM可以理解的代码就说字节码,扩展的.class文件。不面向特定处理器,只面向虚拟机。
优点:解决传统解释型语言执行效率低问题,保留解释型语言可移植的特点。
java从源代码到运行的过程:
.java->javac编译->.class->解释器&JIT编译器->机器可执行代码->执行
第三步到第四步:JVM类加载器先加载字节码文件,通过解释器逐行解释(比较慢)
引用了JIT,属于运行时编译。第一次完成编译后,会将字节码对应的机器码保存下来,下次可以直接使用。JAVA是编译与解释共存的语言
JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。
JIT–实时编译,即时编译(适用于开发调试)
AOT–预先编译,静态编译(使用于部署发布)

JAVA是编译与解释并存

高级编程语言按照执行方式分为两种:
编译型和解释型

  1. 通过编译器将源代码一次性翻译成该平台执行的机器码。编译语言的执行速度快,但开发效率低
  2. 通过解释器一句句将代码解释成机器代码后再执行。解释型语言开发效率快,执行速度慢。
    JAVA语言具有编译型和解释型语言的特征。JVAV先经过编译,后解释。(先编译,生成.class,再由解释器来执行)

Oracle JDK . Open JDK

类似于Oracle主分支,拉出了一个Open分支。响应性和JVM性能方面,Oracle更胜一筹
获取协议不同。第一个是BCL/OTN ,第二个是GPL V2。

JAVA和C++的区别

  1. java不提供指针来直接访问内存,程序内存更安全
  2. JAVA类是单继承,C++的是多重继承。JAVA只有接口才可以多继承
  3. JAVA有GC,就是自动内存管理垃圾回收机制,不需要人工释放内存
  4. C++同时支持方法重载和操作符重载,JAVA只支持方法重载

基本语法

标识符合关键字的区别

标识符是一个自己起的名字,而某些JAVA赋予特殊含义的标识符就是关键字。
注:所有关键字都是小写
default属于程序控制,也属于类,方法和变量修饰符,属于访问控制

类,方法和变量修饰符中:JDK8开始引入默认方法,可以使用default关键字来定义一个方法的默认实现
在访问控制中:如果一个方法前没有任何修饰符,则默认会有一个修饰符 default,但是这个修饰符加上了就会报错

左移运算符<<,向左移若干位,高位丢弃,低位补零。x << 1,相当于 x 乘以 2(不溢出的情况下)。
带符号右移>>,向右移若干位,高位补符号位,低位丢弃。正数高位补 0,负数高位补 1。x >> 1,相当于 x 除以 2。
无符号右移>>>,忽略符号位,空位都以 0 补齐。

移位的位数超过数值所占有的位数

当 int 类型左移/右移位数大于等于 32 位操作时,会先求余(%)后再进行左移/右移操作。也就是说左移/右移 32 位相当于不进行移位操作(32%32=0),左移/右移 42 位相当于左移/右移 10 位(42%32=10)。当 long 类型进行左移/右移操作时,由于 long 对应的二进制是 64 位,因此求余操作的基数也变成了 64。

成员变量和局部变量

语法:成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
存储:从变量在内存中的存储方式来看,如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存
默认值:成员变量如果没有被赋初始值,则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值

静态变量

静态变量可以被类的所有实例共享。一个类创建多少个对象,都共享同一份静态变量。
通常情况,静态变量会被final关键字修饰成为常量

字符型常量和字符串常量

  1. 形式:字符常量是单引号引用的一个字符,字符串常量是双引号引起的0、若干个字符
  2. 含义:字符常量相当于一个整型值(ASCII值),可以参加表达式运算;字符串常量代表一个地址值(该字符串在内存中存放位置
  3. 占内存大小:字符常量(2个字节)(char在java中占两个字节),字符串常量(若干个字节)

静态方法不能调用非静态成员

原因:

  1. 静态方法是属于类,类加载的时候会分配内存,可以通过类名直接访问。非静态成员属于实例对象,只有在对象实例化后才能存在,需要通过类的实例对象去访问。
  2. 类的非静态成员不存在的时候,但静态成员已经存在了。此刻调用在内存中还不存在的非静态成员,是非法操作。

静态方法和实例方法

  1. 调用方式
    外部调用静态方法的时候,是使用的 类名.方法名 的方式,也可以用 对象.方法名 的方式,而实例方法只有后面的方式,不能用第一种方式。
    则:调用静态方法是不需要创建对象的
    注:不建议使用 对象.方法名 的方式调用静态方法。因为静态方法不属于类的某个对象,而是属于这个类。
    一般建议使用 类名.方法名 的方式来调用静态方法
  2. 访问类成员是否存在限制
    静态方法:访问本类的成员时,只允许访问静态成员(静态成员变量和静态方法),不允许访问实例成员(实例成员变量和实例方法)
    实例方法:不存在这个限制

重载和重写

重载:同样的一个方法能够通过不同的输入数据,做出不同的处理
重写:当子类继承父类的相同的方法,输入数据一样,但是对于父类的响应不同于子类的响应时候,就需要覆盖父类的方法,写出该子类需要的响应

重载

发生在同一个类中,或者是父类和子类之间。方法名一定相同,但是参数类型,个数,顺序,方法返回值,访问修饰符可以不同。这就叫重载
注:编译器如果找不到匹配的参数,就会产生编译时错误,因为根本不存在匹配的函数,或者没有一个比其他的更好。这个过程叫重载解析
JAVA允许重载任何方法,而不只是构造器的方法

重写

重写发生在程序的运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
主要有以下三点需要注意:

  1. 首先方法名和参数列表必须相同,子类方法的返回值类型应该要比父类方法的返回值类型更小或相等,抛出的异常范围必须小于等于父类,访问修饰符的范围需要大于等于父类。
  2. 父类方法的访问修饰符是 private/final/static的时候,子类不能重写该昂发,但是被static修饰的方法可以能够被再次声明。
  3. 构造方法不能被重写
    注:构造方法就是 用来实现类的实例化,也就是用来创建对象的,分为有参构造和无参构造
    。主要作用于对象的初始化,一个类中可以定义多个构造方法,加入类中不定义构造方法,则系统会自动为该类生成一个没有参数的构造方法。
    重写就是子类对父类方法的重新改造,外部的样子不能改变,内部的逻辑需要改变。

重写和重载的区别

  1. 重载是同一个类,重写是子类
  2. 重载的参数列表必须修改,重写方法的参数列表不能修改
  3. 重载的返回类型可以修改,重写的子类方法返回值类型应该要比父类方法的返回值类型更小或相等
  4. 重载方法的抛出异常可以修改,重写的抛出异常类应比父类方法声明的抛出的异常类更小或相等
  5. 重载的访问修饰符可以被修改,重写的修饰符可以跟父类一样,或者降低限制
  6. 重载发生在编译期,重写发生在运行期

方法的重写遵循“两同两小一大”

  1. 方法名相同,形参列表相同
  2. 子类方法返回值类型比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应该比父类方法声明抛出的异常类更小或相等
  3. 子类方法的访问权限应该比父类方法的访问权限更大或相等
    注:重写的返回值类型
    如果方法的返回类型是void和基本数据类型,则返回值重写时不能修改。
    如果方法的返回值是引用类型,重写时可以返回该引用类型的子类。
public class Hero {
    public String name() {
        return "超级英雄";
    }
}
public class SuperMan extends Hero{
    @Override
    public String name() {
        return "超人";
    }
    public Hero hero() {
        return new Hero();
    }
}

public class SuperSuperMan extends SuperMan {
    public String name() {
        return "超级超级英雄";
    }

    @Override
    public SuperMan hero() {
        return new SuperMan();
    }
}

可变长参数

定义:允许在调用方法时传入不定长度的参数。可变参数只能作为函数的最后一个参数,但是前面可以有,也可以没有其他任何参数
如果遇到方法重载,则会优先匹配固定参数的方法
JAVA的可变参数通过编译后会被转换成一个数组,可以通过查看编译后生成的class文件

JAVA有8种基本数据类型

JAVA每种基本类型占存储空间的大小不像其他语言随机器硬件架构的变化而变化。这种占存储空间大小的不变性是JAVA程序比其他语言更具有可移植性的原因之一
注:

  1. JAVA中的long类型的数据一定要在数值后加L,否则将作为整型解析
  2. char a = ‘s’; String a = “ss”;
  3. 八种基本类型对应了八种包装类:
    Byte.Short.Integer.Long.Float.Double.Character.Boolean

基本类型和包装类型的区别

  1. 成员变量包装类型不赋值就是null,而基本类型有默认值且不是null
  2. 包装类型可以用于泛型,而基本类型不行
  3. 基本数据类型的局部变量存在JVM的栈中的局部变量表中,基本数据类型的成员变量,没有被static修饰存放在JAVA虚拟机的堆中。包装类型属于对象类型,几乎所有的对象实例存在于堆中
    几乎所有的解释:HotSpot VM引用了JIT优化,会对对象进行逃逸分析,如果发现某一个对象并没有逃逸到方法外部,那么会通过标量替换来实现栈上分配,从而避免堆上分配内存
  4. 相较于对象类型,基本数据类型占用的空间非常小
    注:
    基本数据类型存放在栈中是一个误区。
    基本数据类型的成员变量如果没有被static修饰的话,就放在堆中。

包装类型的缓存机制

缓存机制用来提升性能。
Byte,Short,Integer,Long四种包装类默认创建了【-128,127】的相应类型的缓存数据,
Character创建了数值在【0,127】;Boolean直接返回TRUE,FALSE
浮点数的包装类没有实现缓存机制
所有整型包装类对象之间值的比较,全部使用equals方法:
解释:在整型包装类-128-127之间的赋值,Integer对象是在IntegerCache.cache中产生,会复用已有对象,这个区间内的Integer值可以直接用==进行判断,但是这个区间外的所有数据,都会在堆上产生,并不会服用已有对象

自动装箱和拆箱

装箱:将基本类型用他们对应的引用类型包装起来
拆箱:把包装类型转换成基本数据类型
Integer i = 10 等价于 Integer i = Integer.valueOf(10)
int n = i 等价于 int n = i.intValue();

浮点数运算会有精度丢失的风险

计算机保存浮点数的机制,在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,会导致小数精度发生损失的情况。

解决浮点数运算精度丢失

BigDecimal – 不会造成精度丢失

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);

System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */

超过long的数据表示

JAVA中,64位long整型是最大的整数类型。超过这个范围会有数值溢出的风险

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值