java面试八股文-基础篇

  • A+
所属分类:后端

1、 java语言具有哪些特点?

(1)java语言是一种高级计算语言,是一种面向对象的编程语言,在java的世界中,万物皆为对象;

(2)跨平台性,可能你听说过java的一句经典的话:Write once and run everywhere,一次编写 ,到处运行,这是为什么呢?java利用java虚拟机运行字节码文件,所以不管是什么系统的平台,只要能对java程序进行编译,都是可以运行的;

(3)java是一种解释型语言,编译器把java代码编译成平台无关的中间代码,然后jvm上运行;

(4)java提供很多的内置类库,例如对多线程,对网络通信支持,还有垃圾回收器;

(5)java具有较好的安全性和健壮性,java没有了c++中复杂的指针,还提供了异常处理和垃圾回收机制;

(6)现在在web应用的开发,一般都是使用java语言。

2、面向对象的三大特性

(1)封装:对类的某些数据进行隐藏,外界只能通过对象的方法来获取对象的信息,我们常见的get/set方法和对类的属性私有化就是封装的应用场景。

(2)继承:对象的一个新类可以从现有的类中派生,派生类(子类)可以从它的基类(父类)那继承方法,也可以修改或者新增新的方法;

(3)多态:多态就是不同对象对同一物体或事件发出不同的反应或响应,举个例子:上体育课,铃响了,有的人打篮球,有的人踢毽子,但是都是上体育课,存在多态的必要条件:继承、重写、向上转型(向下转型)。

3、jdk和jre有什么区别?

(1)jdk:java开发工具包,提供了java的开发环境和运行环境

(2)jre:java运行环境,提供了java运行所需的环境

从上面的定义我们就知道了两者的区别在于jdk包含了jre,如果只运行java程序,我们只需要安装jre即可,但是我们要编写java程序,必须得安装jdk。

4、简述一下java修饰符

java常见的几个修饰符有:public、private、protected、default

(1)public:对所有类可见

(2)private:在同一类内可见,但是不能修饰类

(3)default:默认访问修饰符,在同一个包内可见

(4)protected:对同一包内的类和子类可见,不能修饰类

5、构造方法、成员变量初始化以及静态成员变量三者初始化顺序?

(1)先后顺序:静态成员变量、成员变量、构造方法。

(2)详细的先后顺序:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数。

6、接口和抽象类的相同点和区别?

相同点:

(1)都不能被实例化

(2)接口对应的实现类或抽象类对应的子类都需要实现对应的方法才能被实例化

区别:

(1)接口只能有方法的定义,不能有方法的实现,而抽象类可以有方法的定义与实现

(2)实现接口的关键字为implements,继承抽象类的关键字为extends,一个类可以实现多个接口,一个类只能继承一个抽象类,抽象类可以说是一种特殊的类

(3)当子类和父类之间存在逻辑上的层次结构,推荐使用抽象类,有利于功能的积累;而接口的使用为了减低系统的耦合度,方便 日后的维护或添加删除方法。

7、java提供的多态机制

java提供了两种用于多态的机制,分别是重载与覆盖 (1)重载:重载是指同一个类中有多个同名的方法,但是这些方法有不同的参数,在编译期就可以确定调用那个方法;

(2)覆盖(重写):覆盖是指派生类重写基类的方法,使用基类指向子类的实例对象,或接口的引用变量指向其实现类的实例对象,在程序调用的运行期根据引用变量所指的具体实例对象调用正在运行的那个对象的方法,即需要运行期才能确定调用那个方法。

8、重载与重写的区别

(1)重写是父类与子类之间的关系,是垂直关系;重载是同一个类多个方法之间的关系,是水平关系;

(2)重写只能由一个方法或者一对方法产生关系,重载是多个方法之间的关系;

(3)重写要求参数列表相同,重载要求参数列表不同;

(4)重写中,调用方法体是根据对象的类型来决定的,而重载是根据调用时实参表与形参表来对应选择方法体;

(5)重载方法可以改变返回值的类型,重写方法不能改变返回值的类型。

9、final、finally、finalize的区别是什么?

(1)final用于声明属性、方法、类,分别表示属性不可分、方法不可重写、类不可继承

(2)finally作为异常处理的一部分,只能在try/catch语句中使用,finally附带一个语句块表示这个语句最终一定会被执行,经常被用在需要释放资源的情况下;

(3)finalize是object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的finalize()方法,当垃圾回收器准备好释放对象占用空间时首先会调用finalize()方法,并在下一次垃圾回收动作发生时真正回收对象占用的内存。

10、出现java程序中的finally代码块是否一定会执行

当遇到下面情况不会执行 (1)当程序在进入try语句之前就出现异常时会直接结束

(2)当程序在try中强制退出时,比如使用System.exit(0),也不会执行finally块中的代码;当try/catch语句块中有return时,finally语句块中的代码会在return之前执行,如果try/catch/finally块中都有return语句,finally块中的return语句会覆盖try/catch 模块中的return语句。

11、java语言中关键字static的作用是什么?

static的作用:

(1)修饰成员变量:static修饰的变量,可以通过类名.静态变量和对象.静态变量的方式来使用

(2)修饰成员方法:static修饰的方法,无需创建对象就可以被调用,static方法中不能this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和静态成员方法

(3)修饰代码块:jvm在加载类的时候会执行static代码块,static代码块常用于初始化静态变量,static代码块只能执行一次

(4)修饰内部类:static内部类可以不依赖外部类实例对象而被实例化,静态内部类不能与外部类有相同的名字,不能访问普通成员变量,只能访问外部类中的静态成员和静态成员方法。

12、java代码块的执行顺序?

(1)父类静态代码块(只执行一次)

(2)子类静态代码块(只执行一次)

(3)父类构造代码块

(4)父类构造函数

(5)子类构造代码块

(6)子类构造函数

(7)普通代码

13、java中一维数组和二维数组的声明方式?

(1)一维数组的声明方式:

 type arrayName[]
 
 type [] arrayName
复制代码

(2)二维数组的声明方式:

type arrayName[][]

type[][] arrayName

type[]arrayName[]

其中type为基本数据类型或类,arrayName为数组名字

14、String 和Stringbuffer有什么区别?

string用于字符串操作,属于不可变类。string对象一旦被创建,其值不可被改变,而Stringbuffer是可变类,当对象创建后,仍然可以对值进行修改。

15、判等运算符“==”和equals的区别?

==:比较的是引用,equals比较的是内容 (1)如果变量是基本数据类型,==用于比较两者之间的值是否相等;如果变量是两个对象,==用于比较两个对象是否指向同一块存储空间

(2)equals是Object类提供的方法之一,每一个java类都继承自Object类,所以每一个类中都存在equals方法,原生态的equals方法在调用时内部实际是调用==比较对象(通俗讲就是默认比较地址),但是重写equals方法可以让方法比较值,不比较对象。

16、 为什么要把string类设计为不变量?

(1)节省空间:字符串常量存储在JVM的字符串池中可以被用户共享;

(2)提高效率:string会被不同线程共享,线程是安全的,在涉及多线程操作中不需要同步操作;

(3)安全:String常被用于用户名、密码、文件名等使用,由于它的不可变性,可避免黑客行为对其恶意修改。

17、序列化是什么?

序列化是一种将对象转换成字节序列的过程,常常用于解决在对象流进行读写操作所引发的问题,序列化的作用就是持久化一些信息,那我们什么时候需要序列化呢? (1) 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; (2)当你想用套接字在网络上传送对象的时候; (3)当你想通过RMI传输对象的时候;

18、简述java中class对象

在java中对象可以分为实例对象和class对象,每一个类中都有一个class对象,它里面包含了与该类有关的信息,那我们如何获取class对象呢? (1)Class.forName("类的全限定名") (2)实例对象.getClass()方法 (3)类名.class

19、java反射机制是什么?

java反射机制是指在程序运行过程中可以构造任意一个类的对象,获取任意一个类的成员变量和成员方法、获取任意一个对象所属的类的信息、调用任意一个类的属性和方法,反射机制使得java具有动态获取程序信息和调用对象方法的能力,可以通过以下的类调用反射的APl:

class类:可获取类属性方法

Filed类:获得类的成员变量

Method类:获取类的方法信息

Construct类:获取类的构造方法等信息

20、简述注解

java注解用于java代码提供元数据,作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这目的,注解可以用于提供信息给编译器,在编译阶段时给软件提供信息进行相关的处理,在运行时处理写相应代码,做对应操作。

21、简述java异常的分类

java异常分为Erro(程序无法处理的错误),和Exception(程序本身可以处理的异常),这两个类均继承Throwable;

Error常见的有StackOverflowError,OutOfMemoryError等等

Exception可以分为运行时异常和非运行时异常,对于运行时异常,可以利用try catch的方式进行处理,也可以不处理,对于非运行时异常,必须处理,不处理的话程序无法通过编译。

22、简述throw和throws的区别

throw:一般用在方法体的内部,由开发者定义当语句出现问题后主动抛出异常;

thorws:一般用在方法声明上,代表该方法可能会抛出的异常列表。

23、简述泛型

泛型,即是“参数化类型”,解决不确定对象具体类型的问题,在编译阶段有效。泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型在类型中称为泛型类、在接口中称为泛型接口和方法被称为泛型方法。

24、简述泛型擦除

java编译器生成的字节码是不包含泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程被称为泛型擦除。

25、简述java基本数据类型

byte:占用1个字节,取值范围-128127 short:占用2个字节,取值范围-2^152^15-1 int:占用4个字节,取值范围-2^31~2^31-1 long:占用8个字节 float:占用4个字节 double:占用8个字节 char:占用2个字节 boolean:占用大小根据实现虚拟机不同有所差异

26、简述自动装箱拆箱

对于java基本数据类型,均对应一个包装类 装箱就是自动将基本数据类型转换为包装类型,如int->integer 拆箱就是自动将包装器类型装换为基本数据类型,如integer->int

27、简述重载与重写的区别

重写即子类重写父类的方法,方法对应的形参和返回值类型都不能改变

重载即在同一个类中,方法名相同,参数类型或数量不同

28、简述java的多态

Java多态可以分为编译时多态和运行时多态。

编译时多态主要指方法的重载,即通过参数列表的不同来区分不同的方法

运行时多态主要指继承父类和实现接口时,可以通过引用父类指向子类对象,编译看左边,运行看右边

29、简述抽象类与接口的区别

抽象类:体现的is-a的关系,如man is a person,就可以将person定义为抽象类,

接口:体现的是can的关系,是作为模板实现的,如设置接口fly,plance类和bird类均可以实现该接口, 一个类只能继承一个抽象类,但可以实现多个接口

30、简述==和equals方法的区别

对于==,在基本数据类型比较时,是值的比较,对引用数据类型比较时,比较的是其在内存的存放地址;

对于equals方法,在该方法没有被重写时,他的效果与==一致,但是根据用户的需求对其重写,比如直接比较两个对象的属性值是否相同,重写equals方法需要保证equals方法相同对应的对象hashcode也相同。

30、简述Object类常用方法

1、hashCode:通过对象计算出散列码,用于map型或equals方法,需要保证同一个对象多次调用该方法

2、equals:判断两个对象是否一致,需要保证equals方法相同对应的对象hashCode也相等

3、toString:用字符串表示该对象

4、clone:深拷贝一个对象

31、简述内部类及作用

成员内部类:作为成员对象的内部类,可以访问private及以上外部类的属性和方法,外部类想访问内部类属性或方法时,必须要创建一个内部类对象,然后通过该对象访问内部类的属性或方法,外部类也可以访问private修饰的内部类属性

局部内部类:存在于方法的内部类,访问权限类似于局部变量,只能访问外部类的final变量

匿名内部类:只能使用一次,没有类名,只能访问外部类的final变量

静态内部类:类似类的静态成员变量

32、简述String/StringBuffer与StringBuilder

String类采用利用final修饰的字符数组进行字符串保存,因此不可变,如果对String类型对象进行修改,需要新建对象,将老字符串和新增的字符一并存进去

StringBuilder ,采用无final修饰的字符数组进行保存,因此可变,但是他的线程不安全

StringBufer,采用无final修饰的字符数组进行保存,我们可以理解为实现了线程安全的StringBuilder

33、简述java序列化与反序列化的实现

序列化:将java对象转化为字节序列,由此可以通过网络对象进行传输

反序列化:将字节序列转化为java对象

具体实现:实现Serializeable接口,或者实现Externalizable接口中的writeExtermal()与readExternal()方法

34、简述java的list

List是一个有序队列,在java中有两种实现方式:

ArrayList 使用数组实现,是容量可变的非线程安全序列,随机访问快,集合扩容时会创建更大的数组,把原有数组复制到新数组

LinkedList本质是双向链表,与ArrayLiat相比插入和删除速度更快,但随机访问元素很慢,有时我们可以会用LinkedList来替换队列和栈。

35、java中线程安全的基本数据结构有哪些

HashTable:哈希表的线程安全版、但是效率低 ConcurrentHashMap:哈希表的线程安全版,效率高,用于替代HashTable Vector:线程安全版ArrayList Stack:线程安全版栈 BlockingQueue及子类:线程安全版队列

36、简述java的Set

set集合,该集合不允许元素重复且无序,java对set有三种实现方式:

HashSet:HashSet的底层是通过HashMap实现的,HashMap的key即是HashSet存储的元素,Value系统自定义为一个名为PRESENT的Object类型常量,判定元素是否相同,先比较hashCode,相同后再利用equals比较,查询O(1)

LinkedHashSet:继承来自HashSet,通过LinkedHashMap实现,使用双向链表维护元素插入顺序

TreeSet:通过TreeMap实现的,底层的数据结构是红黑树,添加元素到集合是按照比较规则将其插入合适的位置,保证插入后的集合仍然有序,查询O(logn)

37、简述java的HashMap

jdk1.8之前实现是数组+链表,jdk8改成数组+链表+红黑树,主要成员变量包括存储数据的table数组、元素数量size、加载因子loadFactor;

HashMap中数据以键值对的形式存在,键对应的hash值来计算数组下标,如果两个元素key的hash值一样,就会发生哈希冲突,被放在同一个链表上;

table数组记录HashMap的数据,每个下标对应一条链表,所有哈希冲突的数据都会被存放到同一条链表,Node/Entry结点包含四个成员变量:key、value、next指针和hash值,jdk8后链表超过8会转化成红黑树;

扩容: 若当前数据/总数据容量>负载因子,HashMap将执行扩容操作 默认初始化容量为16,扩容容量必须是2的幂次方,最大容量为1<<30、默认加载因子为0.75

38、为什么说HashMap线程不安全

在jdk1.7中,HashMap采用头插法插入元素,因此并发情况下会导致环形链表,产生死循环;

虽然jdk1.8采用了尾插法解决了这个问题,但是并发下的put操作也会使前一个key被后一个key覆盖;

由于HashMap有扩容机制存在,也存在A线程进行扩容后,B线程执行get方法出现失误的情况

39、Collection和Collections有什么区别

1、Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,如List、Set等

2、Collections是一个包装类,包含了很多静态方法,不能被实例化,而是作为工具类使用,比如提供的排序方法: Collections.sort(list);

提供的反转方法:Collections.reverse(list)

40、ArrayList、Vector和LinkedList有什么共同点与区别?

(1) ArrayList、Vector和LinkedList都是可伸缩的数组,即可以动态改变长度的数组

(2)ArrayList和Vector都是基于存储元素的Object[] array来实现的,它们会在内存开辟一块连续的内存空间来存储,支持下标,索引访问,但是在涉及插入元素时可能需要移动容器中的元素,插入效率较低,当存储元素超过容器的初始化容量大小,ArrayList与Vector均会进行扩容

(3)Vector是线程安全的,其大部分方法是直接或者间接同步的,ArrayList不是线程安全的,其方法不具有同步性质,LinkedList也不是线程安全的

(4)LinkedList采用双向列表实现,对数据索引需要从头开始遍历,因此随机访问效率较低,但在插入元素的时候需要对数据进行移动,插入效率较高

41、HashMap与HashTable有什么区别

(1)HashMap是HashTable的轻量级实现,HashMap允许key和value为null,但是最多允许一条记录的key为null,而HashTable不允许;

(2)HashTable中的方法是线程安全的,而HashMap不是,在多线程访问HashMap需要提供额外的同步机制; (3)Hashtable使用Enumeration进行遍历,HashMap使用Iterator进行遍历

42、如何决定使用HashMap还是TreeMap?

如果对Map进行插入、删除或者定位一个元素的操作更频繁,HashMap是更好的选择,如果需要对key集合进行有序的遍历,TreeMap是更好的选择

43、fail-fast和fail-safe迭代器的区别是什么?

(1)fail-fast直接在容器上进行,在遍历过程中,一旦发现容器中的数据被修改,就会被立刻抛出ConcurrentModificationException异常从而导致遍历失败。常见的使用fail-fast方式的容器HashMap和ArrayList等。

(2)fail-safe这种遍历基于容器的一个克隆,因此对容器中的内容修改不影响遍历,常见的使用fail-safe方式遍历的容器有ConcurrentHashMap和CopyOnWriterArrayList

44、HashSet中,equals和hashCode之间的关系

equals和hashCode这两个方法都是从Object类中继承过来的,equals主要用于判断对象的内存地址引用是否是同一个地址;hashCode根据定义的哈希规则将对象的内存地址转换为一个哈希码。HashSet中存储的元素是不能重复的,主要通过hashCode与equals两个方法来判断存储对象是否相同:

1、如果两个对象的hashCode值不同,说明两个对象不相同

2、如果两个对象的hashCode值相同,接着会调用对象的equals方法,如果equals方法的返回结果为true,那么说明两个对象相同,否则不相同

45、拆箱装箱原理

装箱过程是通过调用包装器的valueOf方法实现的,将原值赋给对应类

拆箱过程是通过调用包装器的intValue/doubleValue等方法实现,返回基本的数据类型

46、java反射原理

java会在编译期装载所有的类,并将其元信息保存至Class类对象中。 因此可以设计x.class/x.getClass()/Class.forName()等方法获取class对象。所以在反射调用Field/Method、Constructor对象时,可根据class类对象进行一步操作。

47、compator和compatable的区别

Comparable是一个接口,用于对象内部的比较方式,该接口需要实现的方法是:comparableTo()方法, Comparator也是一个接口,该接口有个compare方法,该接口需要实现的方法是Comparator

47、动态代理实现方式

1、利用JDK反射机制,实现代理接口 2、利用CGLib,对指定类生成子类,进行代理

48、简述OOM(out of memory)

当JVM分配内存不够会抛出out of memory异常

49、简述StackOverFlowError

调用栈深度超过限制产生的异常 一般会在递归调用时出现

w3cjava

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: