转换成自已的语言来回答,来源小林coding、沉默王二以及其它资源和自已改编。
1、概念
1、说一下Java的特点
我认为Java有很多特点
首先是平台无关性:Java可以实现一次编译到处运行,因为Java的编译器将源代码编译成字节码,使得该字节码可以在任意装有JVM的操作系统上运行。
其次是面向对象的性质:Java是面向对象编程语言,这种OOP的特性使得代码易于维护和重用。主要源于封装继承多态这三大特性。
然后是内存管理方面,Java有自己的垃圾回收机制,自动管理内存和不再使用的对象,无需手动管理,减少内存泄漏等问题。
2、Java为什么是跨平台的?
这主要源于JVM的关系。
Java源码经过编译后会生成.class字节码文件,然后由JVM进行翻译成机器码使得程序能够正常运行。
而由于不同的平台它操作系统不一样,所以都会有自己对应版本的JVM,而这些JVM都可以将同样的字节码文件在各自平台上运行产生相同的结果。
其实跨平台的是Java程序,不是JVM。是通过JVM这一桥梁来达成一次编译到处运行的特点。
3、JVM、JDK、JRE三者关系?
JDK是开发工具包,它包括了JRE、编译器、调试器、开发工具等。
JRE是Java运行时环境,包括了运行Java的类库和JVM。
JVM是Java虚拟机,负责将字节码转换成机器码进行执行。使Java程序具备跨平台性。
4、为什么Java解释和编译都有?
因为Java先会将原代码进行编译生成字节码文件,这里体现他的编译性了。
而JVM里有解释器,会逐行解释字节码生成机器码到平台运行,这里体现了他的解释性。
所以说Java是编译与解释并存的语言。
5、编译型语言和解释型语言的区别?
编译性语言:一般的编译型语言会将原代码解析成机器码生成可执行文件再运行,通常速度快但跨平台性差,典型的有C、C++
解释型语言:程序执行时逐行解析代码不生成独立的可执行文件。跨平台性好但速度慢
典型的有python\js
2、数据类型
1、Java有哪些数据类型?
Java数据类型包括基本数据类型和引用数据类型。
基本数据类型有8种:byte\char\short\int\long\double\float\boolean
引用数据类型有3种:数组、类、接口
(浮点数的默认类型是double
整数的默认类型是int
char是无符号的 )
2、long和int可以互转吗?
可以互相转换,但是int转为long是安全的,因为long的范围比int大。而long转int是不安全的,是只会剩下截断后的低四字节,需要注意数据范围。
3、 数据类型转换方式你知道哪些
首先包括隐式转换和显示转换,如果目标类型范围大于当前类型则会隐式转换,而范围小于当前类型则需要强制转换,但此处需要注意数据范围,以免数据损失。
然后还有使用方法进行转换,比如Integer的parseInt方法,可以将字符串转为int
4、类型互转会出现什么问题?
首先目标类型范围小于当前类型则可能会出现数据丢失,会出现截断现象。
而浮点数里double转float则会出现精度损失的问题
还有就是有的类型之间无法转换,比如
boolean
类型不能与任何其他基本数据类型直接互转
5、什么是自动装箱和拆箱?
装箱和拆箱发生在包装类和对应的基本数据类型之间。
装箱可以在赋值和方法调用时使用,会自动将基本类型转换成对应的包装类对象。
拆箱则是反过来,将包装类对象转为基本数据类型
本质上装箱是调用了valueOf方法,拆箱是调用了xxxValue方法
(注意除Character\Integer以外,其它均为首字母大写)
6、Integer比int有哪些优点?说说Interger的缓存。
Integer可以在泛型、集合中应用,更加灵活。因为集合和泛型必须要使用引用类型。
而且Java中绝大部分方法或类都是用来处理类类型对象的,所以包装类也是有必要的
Integer有一个静态缓存池,范围在-128-127之间,在调用valueOf方法时会去缓存池拿,不用新建一个对象。
7、switch 语句能否用在 byte/long/String 类型上?
最开始swich语句只能是 byte、short、char、int。
后来加入了枚举和String类型,但是长整型在目前所有的版本中都是不可以的。
8、说说float怎么存小数的?
包括符号位、尾数、指数
尾数 的第一位总是 1,因此这个 1 可以省略不写,它是个隐藏位
指数 表示 float 时,一共占 8 bit,所以它的取值范围为 0 ~ 255。但因为指数可以是负的,所以规定在存入 E 时在它原本的值加上一个中间数 127,这样 E 的取值范围为 -127 ~ 128。
不过这存在数据不精确的可能,可以使用
BigDecimal来精确计算小数
3、面向对象
1、怎么理解面向对象?简单说说封装继承多态
面向对象是一种编程范式,将现实事物抽象为对象进行交互从而完成程序的功能。而它主要有三大特性。
封装:将属性和方法封装在一起,隐藏起来限制访问,通过特定的方法来进行访问,更加安全。
继承:是子类可以共享父类的属性方法,可以更好的实现代码复用
多态:多态允许不同类的对象对同一消息做出响应,但表现出不同的行为,更加灵活。
2、多态解决了什么问题?
多态主要是指子类可以替换父类,而它也实现动态绑定机制,使程序选择调用哪个类的方法推迟到运行时决定,使得编译类型与运行类型不一样,从而更好的实现一些功能
3、重载与重写有什么区别?
重载:指在一个类中有多个同名方法,但只要他们参数数量、类型、顺序不同就可以根据情况分别调用
重写:指子类可以重新定义父类的方法、但方法名、参数列表、返回类型必须一致。
4、面向对象的设计原则了解哪些?
开放封闭原则:
接口隔离原则:
单一
5、抽象类和普通类的区别?
- 普通类可以实例化,但抽象类不能实例化
- 普通类没有抽象方法,而抽象类可以有抽象方法
- 普通类一般继承其它的类,而抽象类一般用作基类
6、抽象类和接口的区别是什么?
1、一个类只能继承一个抽象类,但却可以实现多个接口。
2、一般情况下接口只有方法的定义没有实现且没有构造方法(1.8可以用default、static)而抽象类可以有定义和实现
3、接口的成员变量是public static final 的,只有静态常量。且所有方法都是public abstract。
抽象类中的成员变量可以在子类 中重新定义和赋值,但若有抽象方法则private、static等修饰。
7、 抽象类可以有构造方法吗?接口呢?
抽象类可以有构造方法,虽然抽象类不能实例化,但他的构造方法会在子类实现的时候调用进行初始化,是由子类间接调用构造方法。
而接口不能有构造方法,因为接口里的变量无需再次初始化,因为他们本身就是必须赋初值的。
8、说说static关键字
static可以修饰变量和方法成为静态变量和静态方法。
静态变量只属于类不属于任何对象,只在类被加载时分配一次内存,但所有的类对象都可以访问,也可以通过类名访问。
静态方法也是只属于类,但不能调用非静态成员,只能使用静态变量和方法。也可以通过类名访问。
9、说说静态内部类和非静态内部类
静态内部类不依赖于外部类,但非静态内部类依赖于外部类
静态内部类只能访问外部类的静态成员,但非静态内部类都可以访问
静态内部类可以定义静态成员,但非静态内部类不可以
10、说说final关键字
当 final 修饰一个类时,表明这个类不能被继承,比如String类
当 final 修饰一个方法时,表明这个方法不能被重写
当 final 修饰一个变量时,表明这个变量的值一旦被初始化就不能被修改。如果是基本类型则值不能变,如果是引用类型则其不能指向其它对象,但指向的内容可以更改
11、非静态内部类可以直接访问外部方法,编译器是怎么做到的?
编译器会在生成内部类实例的时候为他维护一个指向外部类实例的引用,从而能实现直接访问外部类的功能
12、 说说浅拷贝和深拷贝,以及如何实现深拷贝?(后期补充
浅拷贝是指只复制对象本身和其内部的值类型字段,但不会复制对象内部的引用类型字段。
深拷贝是指在复制对象的同时,将对象内部的所有引用类型字段的内容也复制一份,而不是共享引用。
Java里非手动(new 一个再赋值)实现深拷贝可以有两种方式
1、重写Cloneable的克隆方法,引用类型的变量也重新克隆一块地址来存放2、使用序列化和反序列化,
13、说一说泛型
泛型允许类、接口和方法在定义时使用一些类型参数,这些类型参数在使用时可以被指定为具体的类型。使用泛型可以实现多种不同的数据结构实现相同的代码,并限制了类型避免了强制转换出现异常的情况
14、Java创建对象有哪些方式?(后期完成
1、new关键字,调用构造方法创建
2、如果该类实现了Cloneable接口则可以使用clone方法
3、使用反射,使用newInstance方法可以创建
4、序列化和反序列化
15、什么是反射?
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性。
16、==与equals的区别?
==比较的是值,基本类型即为栈中的值,对象比的是指向的是否为同一对象
equals()方法比较的是对象的内容,但默认情况与==一样,只有重写该方法才行,比如String类
17、为什么重写equals时一定要重写hashCode?
因为在使用哈希表类数据结构(HashMap等)时时会使用hashcode来判断两个对象是否相等,hashcode判断的依据是两个对象是否放在同一个位置,这违背了我们的需求,我们只想根据里面的内容来判断相等,所以还需要重写hashcode方法才行
18、new子类时,子类和父类静态代码块、构造方法执行顺序?
- 首先执行父类的静态代码块(仅在类第一次加载时执行)。
- 接着执行子类的静态代码块(仅在类第一次加载时执行)。
- 再执行父类的构造方法。
- 最后执行子类的构造方法。
19、String有哪些常用方法?
length()
- 返回字符串的长度。charAt(int index)
- 返回指定位置的字符。substring(int beginIndex, int endIndex)
- 返回字符串的一个子串,从beginIndex
到endIndex-1
。contains(CharSequence s)
- 检查字符串是否包含指定的字符序列。equals(Object anotherObject)
- 比较两个字符串的内容是否相等。indexOf(int ch)
和indexOf(String str)
- 返回指定字符或字符串首次出现的位置。replace(char oldChar, char newChar)
和replace(CharSequence target, CharSequence replacement)
- 替换字符串中的字符或字符序列。trim()
- 去除字符串两端的空白字符。split(String regex)
- 根据给定正则表达式的匹配拆分此字符串。
20、String\StingBuffer\StringBuilder有什么区别,分别介绍一些?
String的对象是不可变的,实际上每次String对象进行修改操作都会创建一个新的对象。
StringBuilder对字符串的操作是在原本基础上修改的,不会创建大量对象
StringBuffer在StringBuilder的基础上实现了线程安全,使用synchronized关键字适用于多线程环境
21、String str1 = new String("abc") 和 String str2 = "abc" 的区别?
直接使用双引号为字符串变量赋值时,会检查字符串常量池中是否已经存在相同内容的字符串。如果存在,Java 就会让变量引用池中的那个字符串;如果不存在,它会创建一个新的字符串,放入池中,并让变量引用它。
如果使用new的话跟上述步骤一样,但是不会指向常量池中的对象,而是在堆中新建一个副本让变量指向它。
22、String s = new String("abc")创建了几个对象?
如果常量池中存在该字符串则只会在堆中创建一个对象,否则会现在常量池中创建再在堆中创建。
23、String 是不可变类吗?(追问:是的话是如何实现的?)字符串拼接是如何实现的?
是不可变类,因为字符串对象使用非常频繁,尤其是在网络传输中,这样会保证更加的安全。易于重用,而且通过常量池的方式还能减少内存的开销。
实现原理是String类里有final数组来存放字符串,本身类也是final不可被继承修改,而且提供的方法对字符串操作都不会修改源字符串,会新建一个返回。
字符串拼接使用+就行,编译的时候把“+”号操作符替换成了 StringBuilder 的
append()
方法,新建一个StringBuilder对象并toString返回新String对象
24、intern方法有什么作用?
如果当前字符串内容存在于常量池则返回常量池里的对象的引用,如果常量池没有,则将堆中该字符串对象的引用放入常量池,并返回该引用
能减少内存开销,创建的字符串无需很多
25、说说异常
Throwable
是 Java 语言中所有错误和异常的基类。它有两个主要的子类:Error 和 Exception,这两个类分别代表了 Java 异常处理体系中的两个分支。Error:意味程序出现了严重的问题,不应该由异常处理机制来处理,程序应该崩溃掉。
如Stackoverflow\outofmemory等
Exception:程序出现了在可控范围内的异常,可以人为处理解决
26、说说检查型异常和非检查型异常
检查型异常:由编译器检查的异常,程序员必须显式处理或声明这些异常,不处理的话编译器将报错。如文件不存在、类未找到等
非检查型异常: 运行时由程序错误导致,不需要在编译强制捕获或声明,程序员可以选择处理这些异常,它们通常为Runtimeexception及其子类、如空指针异常等
27、异常的处理方式?
遇到异常时可以不处理,直接通过throw 和 throws 抛出异常,交给上层调用者处理。
throws 关键字用于声明可能会抛出的异常,而 throw 关键字用于抛出异常。
第二种是使用 try-catch 捕获异常,处理异常
28、 什么是序列化和反序列化?
序列化是将对象转换为字节流的过程,以便能够保存到数据库或文件中
反序列化是将字节流转换为对象的过程。
实现Serializable接口可以被序列化
29、什么是反射?原理是什么?
在运行时,能够知道任意一个类的所有属性和方法,对于任意一个对象都可以调用他的任意一个方法和属性。
Java 程序的执行分为编译和运行两步,编译之后会生成字节码(.class)文件,JVM 进行类加载的时候,会加载字节码文件,将类型相关的所有信息加载进方法区,反射就是去获取这些信息,然后进行各种操作。
30、什么是注解?
注解本质上是一个标记,可以标在类方法属性上,通过识别这些标记可以进行其它的操作
注解生命周期有三大类,分别是:
- RetentionPolicy.SOURCE:给编译器用的,不会写入 class 文件
- RetentionPolicy.CLASS:会写入 class 文件,在类加载阶段丢弃,也就是运行的时候就没这个信息了
- RetentionPolicy.RUNTIME:会写入 class 文件,永久保存,可以通过反射获取注解信息
31、Jdk1.8新特性
Java 8 允许在接口中添加默认方法和静态方法。
还有 Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行
还提供了Stream流,方便我们进行一些操作
32、多态的底层原理说说?
多态最主要的实现就是向下转型,原理是jvm会为每个对象在方法区建立一个方法表,方法表的表项存放的是方法的地址。如果子类重写了父类的方法则地址为子类方法的地址,如果未重写 则放的是父类该方法的地址,也就是把父类的同名方法地址copy过来