当前位置:   article > 正文

Java基础面试题(1)

java基础面试

Java基础面试题(1)

面向对象有哪些特征

java的8种基本数据类型

Java中有8种基本类型,分为4类,分别为:
整型:包括  byte ,short, int , long
浮点型:float,double
字符型:char
布尔类型:boolean
  • 1
  • 2
  • 3
  • 4
  • 5

对于short s1=1;s1=s1+1;这两句代码会报错,为什么呢?因为byte,short类型在相加的时候,会自动的提升到int类型,所以用short类型的变量接收int类型的结果会报错。

装箱和拆箱

自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,把double转化成Double,等等。反之就是自动拆箱。

原始类型:byte,short,int,long,float,double,char,boolean

封装类型:Byte,Short,Integer,Long,Float,Double,Character,Boolean

int和Integer的区别

1.Integer是对象类型,而int是java的一种基本类型

2.Integer的默认值是null,而int的默认值是0

关于int和Integer的比较

1.由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new 生成的Integer变量永远不相等,因为这两个实例化对象都是在堆内存中,它们的内存地址不同。

Integer i=new Integer(100);
Integer j=new Integer(100);
System.out.println(i==j);//false
  • 1
  • 2
  • 3

在这里插入图片描述

2.int类型的变量和Integer类型的变量进行比较的时候,Integer类型的变量会自动拆箱,所以只要二者的值相同,那么比较结果就是true,相当于是两个int类型在比较

Integer i=new Integer(100);
int j=100;
System.out.println(i==j);//true
  • 1
  • 2
  • 3

在这里插入图片描述

3.非new生成的Integer变量和new生成的Integer变量的比较结果肯定是false,为什么呢?因为非new生成的Integer变量指向的是方法区中的常量池中的对象,而new生成的Integer变量指向的是堆区的对象,所以这两个变量的值肯定是不相同的

Integer i=new Integer(100);
Integer j=100;
System.out.println(i==j);//false
  • 1
  • 2
  • 3

在这里插入图片描述

4.如果两个Integer变量都是通过非new的形式创建的,那么如果两个变量的值相同,并且区间在-128127之间,这两个变量都指向方法区中的常量池中的对象,这两个变量相同,比较结果为true,但是如果这两个变量的值相同,但是不在区间-128127之间,那么这两个变量指向堆区中的对象,比较结果为false

Integer i=120;
Integer j=120;
System.out.println(i==j);//true

Integer i2=150;
Integer j2=150;
System.out.println(i2==j2);//false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

String转化成int类型能不转?怎么转?

使用Integer.parseInt(str);可以把String类型的字符串转化成int类型,但是这个过程中可能会出现NumberFormatException异常,那么什么时候会出现异常呢?当str字符串不是完全数字字符串的形式的时候,如String str=“123e”;这种形式在转化的时候就会出现异常;如果字符串str=null;那么在转化的时候也会出现NumberFormatException异常;即便是字符串完全是数字的形式如String str=“1111111111111”;这样也会报错,为什么呢?因为范围超过了int类型的范围,那怎么办呢?使用Long.parseLong(str);进行字符串的转化,转化成long类型;

创建对象的五种方式

1.使用new

2.使用Class.newInstance()

3.使用Constructor.newInstance()

在这里插入图片描述

4.使用clone方法

在这里插入图片描述

5.使用反序列化

反序列化就是从磁盘中的文件中读取对象

在这里插入图片描述

JDK,JRE,JVM

一张图让你明白JDK,JRE,JVM三者的关系,如下图:

img

从图中可以看出JDK包含JRE,JRE又包含JVM。

JDK:java development kit (java开发工具)

JRE:java runtime environment (java运行时环境)

JVM:java virtuak machine (java虚拟机)

JRE是java运行时环境,它包括Java虚拟机,Java核心类库和支持文件,它不包括编译器,调试器等其他工具。

JDK包括JRE和编译器调试器等其他工具。

static和final的区别

static:

修饰变量:静态变量随着类加载时完成初始化,内存中只有一个,且JVM只会为它分配一次内存,所有对象共享静态变量。

修饰方法:在类加载的时候就存在,不依赖任何实例,所有对象共用一个静态方法;静态方法必须要实现,不能用abstract修饰。为什么呢?当我没有看《Java编程思想》这本书的时候,我只是为了应付面试,单纯的把这句话背了下来,并没有去理解它的内部逻辑,但是当我看过《Java变成思想》这本书的时候,里面有个思想对我触动非常大,就是对象你可以把它看成是“服务提供者”,它就是向别的对象提供服务的,而我们的程序其实就是一系列对象组成,而程序就是向用户提供服务的。如果你的类型class中的一个方法使用了static修饰成了静态方法,那么你的这个方法虽然可以被其他的class类型继承,但是在这个子class类型中,你却不能够重写static静态方法,那么这就要求我们,class类型中向外功能服务也就是calss类型中定义的方法,如果它是静态的,那么就肯定不能是抽象的,因为抽象的方法,它是没有功能的,而一个static静态方法又不能被重写,所以这就会导致,class类型中的这个static功能一直什么功能都不能实现,这就违背了我们的对象可以看成“服务提供者”这一原则。

final:

修饰变量:如果修饰的是基本类型的变量,那么在编译之前就必须要为这个变量赋值,以后这个变量就相当于是一个常量,它的值就不能更改了;如果修饰的是对象类型,那么这个对象的引用地址不能变,但是对象在堆内存中的内容可以变。

修饰方法:不能被子类修改。

修饰类:类不能被继承。

被static修饰的方法是不可以被重写的,如下图:

在这里插入图片描述

public,protected,default,private修饰符

这三个修饰符可以修饰的范围如下图

img

equals和==的区别以及hashCode方法的解释以及map集合中是怎样做到元素不重复的?

==的解释说明

两个基本类型用==比较,比较的是内容;

两个对象类型用==比较,比较的是对象的存放地址;

equals的解释说明

对象中如果重写了equals方法,那么比较的是内容;

对象中如果没有重写equals方法,那么比较的还是对象的存放地址;

hashCode方法的解释

java中要求,两个对象调用hashCode的值如果相同,必须要保证这两个对象是相同的;没有重写equals方法和hashCode方法之前,equals方法比较的是两个对象的内存地址,而hashCode会根据对象的内存地址生成一个数值,如果用equals比较的两个对象地址相同,那么两个对象调用hashCode的值也必须要相同;但是如果重写了equals方法,那么两个对象调用equals方法比较的时候,就不是根据地址比较了,而是根据对象的内容进行比较,但是这个时候hashCode方法仍是根据对象的地址生成一个数值,所以这个时候会出现一个问题,就是两个对象用equals方法比较的是相同的,但是这两个对象调用hashCode方法之后的返回值却是不相同的,这样的话就不满足两个对象如果用equals方法比较的结果相等,那么这两个对象调用hashCode方法的返回值也相同了。因此如果要重写equals方法,那么一定也要同时重写hashCode方法,这样的话,hashCode方法也是根据对象的内容生成一个数值,就不再是根据地址生成数值了,总之,equals方法和hashCode方法要时刻保持一致。

map集合中实现元素不重复的底层代码

每个对象在加入到map集合中,用到的两个最关键的方法一个是hashCode方法,另外一个是equals方法。还会用到散列表。

首先map集合会取对象的hashCode方法返回的hashCode值,然后把hashCode值作为散列表的哈希函数的输入参数,然后哈希函数会返回一个值,这个值叫做哈希值。然后map集合会去寻找哈希列表对应的内存单元是否存在元素,如果不存在元素,证明map集合中没有要添加的对象,直接把这个对象添加到对应的内存单元即可。但是如果存在元素的话,会调用要添加对象的equals方法和这个内存单元中的每个元素逐一比较,如果有相等的对象,说明map集合中已经有这个对象了,那么会放弃添加对象;如果比较之后发现没有相等的,则说明map集合中没有要添加的对象,这个时候直接添加这个对象即可。

在这里插入图片描述

接口和抽象类的区别

1.接口和抽象类中的变量访问类型不同,如下图:

在这里插入图片描述

在这里插入图片描述

2.抽象类中可以有构造方法但是接口中不能有构造方法

在这里插入图片描述

在这里插入图片描述

3.接口中只能包含抽象方法,而抽象类中可以包含抽象方法和普通方法

在这里插入图片描述

在这里插入图片描述

4.一个类可以实现多个接口,但是只能继承一个抽象类

5.抽象类可以用final修饰符修饰吗?不可以,如果抽象类使用了final修饰符修饰,那么这个抽象类就不能够被继承了,而被继承是抽象类的唯一功能,所以不能用final修饰符修饰抽象类。

6.抽象类和接口都不能被实例化。抽象类的主要功能是被其它类继承,而接口的主要功能是被其它类实现。

面向对象的三大特征

1.封装

隐藏对象的属性和方法,仅把公共的东西提供给外界。这样的好处是,我们可以把不想要给外界展示的东西隐藏起来,这样比较安全。

2.继承

继承使用关键字extends,继承只能是单继承,如果A类继承了B类,那么A类将拥有B类的属性和方法。

3.多态

什么叫做多态?就是同一个接口对象,使用不同的实例,调用接口对象的相同的方法会有不同的执行结果。

能够多态的前提:

a.必须有继承关系

b.必须要有实现的方法

c.必须要有父类指向子类的引用。

多态的好处:

可以提高程序的可扩展性;

多态的弊端:

只能执行父类中存在的方法,如果子类中存在父类中不存在,那么这个方法是不能执行的。

可以体现多态的例子如下图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

方法的重载和重写

方法的重载:

方法的重载指的是在同一个类中,有很多的相同名字的方法,这就叫做方法的重载。怎样区分方法的重载?如果在同一个类中两个方法的名字相同,类型相同,只要参数类型或者参数个数有一个不相同,那么这两个方法就叫做方法的重载。

为什么不可以通过方法的返回值来区分方法的重载?

因为编译器无法确定,你调用的到底是哪个方法。你比如

void max(int a,int b){...}
int max(int a,int b){...}
  • 1
  • 2

那么在程序调用max方法的时候,就不知到到底调用哪个方法。

方法的重写

方法的重写牵涉到子类和父类,方法的重写是在子类中重写父类中的方法,要求这两个方法必须要有相同的名字和相同的返回值类型。

列出一些常见的运行时异常

ArithmeticException(算术异常)

ClassCastException(类型转换异常)

IllegalArgumentException(非法参数异常)

IndexOutOfBoundsException(下标越界异常)

NullPointerException(空指针异常)

OutOfMemory(内存溢出异常)

List,Set,Map是否继承自Collection接口

Java集合可以分为Collection和Map两种体系,其中List接口和Set接口都继承于Collection接口,而Map接口它自己和Collection接口一样,也是一个独立的体系。

List接口存储的是有序可重复的数据,它主要有三个实现类,ArrayList,LinkedList,Vector

Set接口存储的是无序不可重复的数据,它主要的三个实现类,HashSet,LinkedHashSet,TreeSet

Map接口主要存储的是键值对key-value,它的主要的实现类,HashMap,LinkedHashMap,TreeMap,HashTable,Properties

阐述ArrayList,Vector,LinkedList的存储性能和特性

ArrayList和Vector底层都是使用的数组存储数据,因此对于ArrayList和Vector容器,查询数据的时候会很快,直接通过数组下标就可以查询,但是插入数据的时候牵涉到数组元素的前后移动,所以会很慢;

LinkedList采用的是双向链表存储数据,因此对于LinkedList容器,查询数据的时候需要进行向前后向后遍历,所以会很慢,但是插入数据的时候只需要断开插入元素链表中前后项的连接即可,所以速度会很快。

Vector底层使用了synchronized修饰,因此Vector是线程安全的容器,而ArrayList和LinkedList都是线程不安全的容器。

Collection和Collections的区别

Collection是一个接口,它是Set,List容器的父接口;Collections是一个工具类,提供了一系列的静态方法来帮助集合容器进行操作,比如说Collections工具类可以对Set,List集合容器中的所有元素进行随机排序,或者是升序排序等操作。

TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

TreeSet和TreeMap都可以对插入的元素进行自动排序,对于TreeSet来说,插入的元素必须要是同一类型的对象,而对于TreeMap来说,插入的key-value键值对中的key必须要是同一类型的对象。

TreeSet要求存放的对象所属的类必须要实现Comparable接口,该接口提供了compareTo()方法,在插入对象所属的类中需要实现compareTo()方法,然后TreeSet容器会根据存放对象所属的类中实现的compareTo()方法对存放的对象进行自然排序,如下图:

在这里插入图片描述

在这里插入图片描述

TreeMap容器存放的key-value键值对中的key对象所属的类型必须也要实现Comparable接口,TreeMap容器会按照存放的键值对key-value中的key对象所属的类型中的compareTo()方法定义的排序规则进行自然排序,如下图:

在这里插入图片描述

在这里插入图片描述

Collections工具类中的sort()方法如何比较元素?如下图:

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/124520
推荐阅读
相关标签
  

闽ICP备14008679号