文章目录Java基础面试题1面向对象有哪些特征java的8种基本数据类型装箱和拆箱String转化成int类型能不转怎么转创建对象的五种方式JDK,JRE,JVMstatic和final的区别public,protected,default,private修饰符equals和的区别以及hashCode方法的解释以及map集合中是怎样做到元素不重复的接口和抽象类的区别面向对象的三大特征方法的重载和重写列出一些常见的运行时异常List,Set,Map是否继承自Collection接口阐述ArrayList,Vector,LinkedList的存储性能和特性Collection和Collections的区别TreeMap和TreeSet在排序时如何比较元素Collections工具类中的sort()方法如何比较元素?Java基础面试题1面向对象有哪些特征java的8种基本数据类型Java中有8种基本类型分为4类分别为 整型:包括byte,short,int,long浮点型:float,double字符型:char布尔类型:boolean对于short s11;s1s11;这两句代码会报错为什么呢因为byteshort类型在相加的时候会自动的提升到int类型所以用short类型的变量接收int类型的结果会报错。装箱和拆箱自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,把double转化成Double,等等。反之就是自动拆箱。原始类型:byte,short,int,long,float,double,char,boolean封装类型:Byte,Short,Integer,Long,Float,Double,Character,Boolean为什么java中会引入自动装箱与自动拆箱泛型。java泛型中不能引入基本类型只能引入对象类型。那有些时候我就是需要泛型置顶为基本类型使用基本类型肯定就不行了这个时候必须使用对象类型。所以就有了java基本类型的装箱。集合。不管是list集合还是map集合它里面都是只能存储对象类型的元素不能存储基本类型的元素。而有些时候我们就是想要让这个集合里面存储基本类型数据那么这个时候就会报错了。而引入了自动装箱机制可以解决这个问题。自动装箱都是自动的比如你写了代码list.add(10); 其实这里会自动执行Integer.valueOf(10)命令。上面是为什么会出现自动装箱那么又为什么会出现自动拆箱呢自动拆箱主要是好计算把包装类型拆成基本类型直接相加就可以了。如果是对象类型的话不好计算我还需要去找这个对象在内存中的地址还要找它的属性就比较麻烦比较耗费性能。int和Integer的区别1.Integer是对象类型而int是java的一种基本类型2.Integer的默认值是null而int的默认值是0关于int和Integer的比较1.由于Integer变量实际上是对一个Integer对象的引用所以两个通过new 生成的Integer变量永远不相等因为这两个实例化对象都是在堆内存中它们的内存地址不同。IntegerinewInteger(100);IntegerjnewInteger(100);System.out.println(ij);//false2.int类型的变量和Integer类型的变量进行比较的时候Integer类型的变量会自动拆箱所以只要二者的值相同那么比较结果就是true,相当于是两个int类型在比较IntegerinewInteger(100);intj100;System.out.println(ij);//true3.非new生成的Integer变量和new生成的Integer变量的比较结果肯定是false,为什么呢因为非new生成的Integer变量指向的是方法区中的常量池中的对象而new生成的Integer变量指向的是堆区的对象所以这两个变量的值肯定是不相同的IntegerinewInteger(100);Integerj100;System.out.println(ij);//false2026/5/21再次解释为什么非new创建的Integer对象与new创建的Integer对象二者比较一定不相等如果是new的Integer对象比如Integer num new Integer(10)那么一定会去堆区中创建一个新的对象的会出现一个新的内存地址所以这个内存地址一定是新的而如果是直接创建的Integer对象比如Integer num 10那么它会进行自动装箱这里有个很关键的点对于方法区主要是存放我们的常量值的为了避免创建过多的对象我们会在方法区存放一些常用的常量值比如-128 ~ 127 这个数字在方法区会有特定的对象地址这样就可以避免过多的创建对象了。所以Integer num 10这行它一定是取的方法区的对象地址而Integer num new Integer(10)它是在堆区中新创建的一个对象因此二者的地址肯定不一样。4.如果两个Integer变量都是通过非new的形式创建的那么如果两个变量的值相同并且区间在-128127之间这两个变量都指向方法区中的常量池中的对象这两个变量相同比较结果为true,但是如果这两个变量的值相同但是不在区间-128127之间那么这两个变量指向堆区中的对象比较结果为falseIntegeri120;Integerj120;System.out.println(ij);//trueIntegeri2150;Integerj2150;System.out.println(i2j2);//falseString转化成int类型能不转怎么转使用Integer.parseInt(str);可以把String类型的字符串转化成int类型但是这个过程中可能会出现NumberFormatException异常那么什么时候会出现异常呢当str字符串不是完全数字字符串的形式的时候如String str“123e”;这种形式在转化的时候就会出现异常如果字符串strnull;那么在转化的时候也会出现NumberFormatException异常即便是字符串完全是数字的形式如String str“1111111111111”;这样也会报错为什么呢因为范围超过了int类型的范围那怎么办呢使用Long.parseLong(str);进行字符串的转化转化成long类型创建对象的五种方式1.使用new2.使用Class.newInstance()3.使用Constructor.newInstance(4.使用clone方法5.使用反序列化反序列化就是从磁盘中的文件中读取对象JDK,JRE,JVM一张图让你明白JDK,JRE,JVM三者的关系如下图:从图中可以看出JDK包含JRE,JRE又包含JVM。JDKjava development kit java开发工具JREjava runtime environment java运行时环境JVMjava 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修饰符这三个修饰符可以修饰的范围如下图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.必须要有父类指向子类的引用。多态的好处:可以提高程序的可扩展性多态的弊端只能执行父类中存在的方法如果子类中存在父类中不存在那么这个方法是不能执行的。可以体现多态的例子如下图方法的重载和重写方法的重载:方法的重载指的是在同一个类中有很多的相同名字的方法这就叫做方法的重载。怎样区分方法的重载如果在同一个类中两个方法的名字相同类型相同只要参数类型或者参数个数有一个不相同那么这两个方法就叫做方法的重载。为什么不可以通过方法的返回值来区分方法的重载?因为编译器无法确定你调用的到底是哪个方法。你比如voidmax(inta,intb){...}intmax(inta,intb){...}那么在程序调用max方法的时候就不知到到底调用哪个方法。方法的重写方法的重写牵涉到子类和父类方法的重写是在子类中重写父类中的方法要求这两个方法必须要有相同的名字和相同的返回值类型。列出一些常见的运行时异常ArithmeticException算术异常ClassCastException(类型转换异常)IllegalArgumentException(非法参数异常)IndexOutOfBoundsException(下标越界异常)NullPointerException(空指针异常)OutOfMemory(内存溢出异常)List,Set,Map是否继承自Collection接口Java集合可以分为Collection和Map两种体系其中List接口和Set接口都继承于Collection接口而Map接口它自己和Collection接口一样也是一个独立的体系。List接口存储的是有序可重复的数据它主要有三个实现类ArrayList,LinkedList,VectorSet接口存储的是无序不可重复的数据它主要的三个实现类HashSet,LinkedHashSet,TreeSetMap接口主要存储的是键值对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()方法如何比较元素如下图: