java integer valueof_Java面试题大全(二)

关注·

点击蓝字,关注我吧

 Java常见面试题大全第二部分来啦,请查收,文末附电子版下载方法,篇幅较长,都是干货,赶紧收藏起来吧!e3f77db80c468e8f27dbd5fa32f0a6a7.png

11、intInteger有什么区别?基本数据类型和基本数据类型包装类有什么异同?为什么有基本数据类型还要有基本数据类型包装类?

Java是面向对象的程序设计语言,讲究的是万物皆对象的理念。而基本数据类型在某些场景下无法使用,包装类可以向操作其它类一样简单操作对“基本数据类型进行操作”;

包装类提供了更多更实用的方法,如hashCode方法,equals方法以及valueOf方法等等,功能比基本数据类型丰富。从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

Java 为每个原始类型提供了包装类型:

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

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

基本数据类型与基本数据类型比较

1)重写了hashcode和equals方法还有其它比较实用的方法,如valueOf、parseInt、parseDouble、toHexString等数值的常用进制转换方法等等。(使用包装类型进行值比较时,建议使用equals方法,而不是使用==去进行值比较,这是因为包装类型中对一个范围的数字使用了一种类似类似缓存池的东西,下面的例子将会介绍)

2)包装类可以为泛型参数,而基本数据类型不可以。例如我们定义一个List集合时,可以使用包装类型,但是却无法使用基本数据类型。

3)包装数据类型都实现了Serializable接口,所以可以序列化和反序列化。

扩展:(1)把对象转换为字节序列的过程称为对象的序列化;把字节序列恢复为对象的过程称为对象的反序列化。

   (2)对象的序列化主要有两种用途:第一种用途:把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;第二种用途:在网络上传送对象的字节序列。

4)基本数据类型的默认值与基本数据类型的包装类的默认值不同。包装类因为是类,所以包装类的默认值为null;基本数据类型,byte、short、int、long为0,boolean默认为false,float和double为0.0,char类型默认为空(不是null哦)

光说不练假把式,请看如下程序:

public class DataTest {    public static void main(String[] args) {        // 定义了一个字符串,字符串的内容为256        String numberString = "252";        // Integer中的parseInt方法返回值类型为Integer        // 之所以能用int类型去接,是因为自动拆箱,将包装类型拆箱为基本数据类型        int number = Integer.parseInt(numberString);        // number 为基本数据类型,进行加4操作,返回的应该是基本数据类型中的int型        // 之所以能用Integer包装类型去接,是因为自动装箱,将int数据类型自动装箱        Integer hexInteger = number + 4;        // 可以对包装类型赋值像给基本数据类型中的int赋值一样,自动装箱        // int自动装箱调用了Integer中的valueOf方法(请注意此方法)        // 下面等同于 Integer equalsInteger = Integer.valueOf(256);        Integer equalsInteger = 256;        // 这里很容易理解,==比较的是两个对象的地址,hexInteger和equalsInteger        // 是两个不同的Integer对象,他们的地址是不同的,==比较结果是false        // 比较结果为false,但是如果我们将数换为64呢?==比较的结果如何???        System.out.println(hexInteger == equalsInteger);        // 包装类型都重写了equals方法,所以这里比较的是两个对象的值内容       System.out.println(hexInteger.equals(equalsInteger));        // 将数字转化为16进制字符串        System.out.println(Integer.toHexString(hexInteger));    }}

程序运行结果如下:

99a57ead10ebd70c2b3ac424fdf32cfb.png

在上述程序示例中的一个问题,如果我们换成64呢?结果还是一样吗?
public class DataTest {    public static void main(String[] args) {        // 定义了一个字符串,字符串的内容为60        String numberString = "60";        // Integer中的parseInt方法返回值类型为Integer        // 之所以能用int类型去接,是因为自动拆箱,将包装类型拆箱为基本数据类型        int number = Integer.parseInt(numberString);        // number 为基本数据类型,进行加4操作,返回的应该是基本数据类型中的int型        // 之所以能用Integer包装类型去接,是因为自动装箱,将int数据类型自动装箱        Integer hexInteger = number + 4;        // 可以对包装类型赋值像给基本数据类型中的int赋值一样,自动装箱        // int自动装箱调用了Integer中的valueOf方法(请注意此方法)        Integer equalsInteger = 64;        // 比较结果为false,但是如果我们将数换为64呢?==比较的结果如何???        System.out.println(hexInteger == equalsInteger);        // 包装类型都重写了equals方法,所以这里比较的是两个对象的值内容   System.out.println(hexInteger.equals(equalsInteger));        // 将数字转化为16进制字符串     System.out.println(Integer.toHexString(hexInteger));    }}
程序输出结果如下:

e03f2f849a4f6d0050cadff259881b36.png

这里改为64以后,为什么==比较也是true了呢? 这里就需要对装箱的实现以及装箱的概念有所了解。当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,看看valueOf方法的源码就知道了,valueOf方法源码如下:
public static Integer valueOf(int i) {    if (i >= IntegerCache.low && i <= IntegerCache.high)     return IntegerCache.cache[i + (-IntegerCache.low)];     return new Integer(i); }
这里面有一个IntegerCache是Integer的内部类,其代码如下:
private static class IntegerCache {    static final int low = -128;    static final int high;    static final Integer cache[];    static {         // high value may be configured by property         int h = 127;         String integerCacheHighPropValue =         sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");         if (integerCacheHighPropValue != null) {              try {                  int i = parseInt(integerCacheHighPropValue);                  i = Math.max(i, 127);                   // Maximum array size is Integer.MAX_VALUE                   h = Math.min(i, Integer.MAX_VALUE - (-low) -1);               } catch( NumberFormatException nfe) {                  // If the property cannot be parsed into an int, ignore it.              }           }           high = h;           cache = new Integer[(high - low) + 1];           int j = low;           for(int k = 0; k               cache[k] = new Integer(j++);            // range [-128, 127] must be interned (JLS7 5.1.7)            assert IntegerCache.high >= 127;        }        private IntegerCache() {}}
简单的说,如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,超出这个范围的数值才会真正的new一个对象出来。所以上面的两段程序的输出结果是不一样的。 扩展:基本数据类型包装类中的Byte、Short、Integer、Long的高频缓存范围为-128到127;Character的高频缓存为0到127;Float、Double没有高频缓存区。Integer是唯一一个可以修改高频缓存范围的包装类。通过在VM optons中如下设置:-XX:AutoBoxCacheMax=8866 即修改缓存最大值为8866。 再看如下程序:
public class DataTest {    public static void main(String[] args) {        int a = 100;        Integer b = new Integer(100);        Integer c = new Integer(100);        System.out.println(a == b);        System.out.println(a == c );        System.out.println(b == c);        System.out.println(b.equals(a));        System.out.println(c.equals(a));        System.out.println(b.equals(c));    }}
程序运行结果如下:

9cff426ec1b3469cea5b77794345015e.png

a与b、a与c使用==比较,会将Integer包装类自动拆箱为基本数据类型中的int,进行值比较与a与b、a与c、b与c使用equals(包装类重新了equals方法)方法一样进行的都是值比较,所以是true;而b与c使用==进行比较的结果却为false,这是因为new出来的对象不会使用高频缓存范围的数值,是先创建对象,这两个对象是不同的对象,所以地址是不同的,返回false;(当然这么写代码,如果你的编程软件安装了阿里代码开发检测工具的时候是会有黄色警告的)
12、在程序中选择包装类还是基本类的原则有哪些?
包装类型比基本数据类型的应用范围更广,同时提供了很多方法,很方便,一般情况下确定是使用基本数据类型还是包装类型原则如下: 1)所有的POJO类属性必须使用包装类; 2)RPC中的方法返回值和参数必须使用包装类; 3)所有局部变量推荐使用基本数据类型;
13、泛型可以为基本类型吗?为什么?
泛型不能使用基本数据类型。泛型在 JVM(Java虚拟机)编译的时候会类型檫除,比如代码 List list 在 JVM 编译的时候会转换为 List list ,因为泛型是在 JDK 5 时提供的,而 JVM 的类型檫除是为了兼容以前代码的一个折中方案,类型檫除之后就变成了 Object,而 Object 不能存储基本数据类型,但可以使用基本数据类型对应的包装类,所以像 List list 这样的代码是不被允许的,编译器阶段会检查报错,而 List list 是被允许的。
14、3*0.1==0.3的比较结果?
比较结果为false。浮点数在计算机中不能准确的表示出来,3*0.1结果输出为0.30000000000000004; 扩展:有的人说在0.1改为0.1f结果就为true了,这里是错误的,因为3*0.1f结果为float,结果为0.3没问题,但是与0.3(小数类型没有显式定义数据类型的话,默认是double)比较,会将float的0.3隐式转换为double类型,还是0.30000000000000004与0.3比较,所以还是false; 测试程序如下:
public static void main(String[] args) {float a = 1.2f;double b = a;    System.out.println(a);    System.out.println(b);    System.out.println(3*0.4f);    System.out.println(1.2);    System.out.println( (float)(3*0.4)== 1.2);}
程序输出结果:

d5fe255d9174da00850cf7036202af99.png

15、equals和 == 的区别?
对于基本数据类型比较的是值,对于引用类型来说 == 比较的变量是栈内存中存放的地址信息是否相同,用来判断两个对象的地址是否相同,即是否指向相同的对象。equals在重写了equals方法后比较的是值的信息是否相同。equals方法最先比较的就是hashCode方法是否相同,如果一个类没有重写equals方法,则equals和==的作用是相同的,这是因为所有的类都继承于Object 超类,而Object超类中的equals方法返回是用==判断的。String对象和Integer对象都重写了equals方法。重写equals方法一定也要重写hashcode方法。 扩展:重写hashCode方法和equals方法的几种方式(当然也可以自己重写)

93d0e3545aaa6f192b76e44ca9e92fdb.png

如下面程序:
public static void main(String[] args) {    String s1 = "abc";    String s2 = new String("abc");    String s3 = new String("abc");    System.out.println("s1与s2使用==比较结果:" + (s1 == s2));    System.out.println("s1.equals(s2)使用equals比较结果:" + s1.equals(s2));    System.out.println("s2与s3使用==比较结果"+ (s2 == s3));    System.out.println("s2与s3使用equals比较结果" + s2.equals(s3));}
程序运行结果:(一定要注意基本数据类型包装类中的常用高频数值范围,可能会出现不一样的结果)

01e84ce91d149960154282863da6267e.png

16、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。 扩展:equals方法介绍:首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。 实现高质量的equals方法的诀窍包括:1. 使用==操作符检查"参数是否为这个对象的引用";2. 使用instanceof操作符检查"参数是否为正确的类型";3. 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;4. 编写完equals方法后,问自己它是否满足对称性、传递性、一致性;5. 重写equals时总是要重写hashCode;6. 不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。
17、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
Java中只有值传递。Java语言的方法调用只支持参数的值传递(Java中没有指针)。函数调用时,无论值类型变量还是引用类型变量,都是将变量所存储的值copy给了函数的实参,区别在于基本类型变量的值就是类型值本身,而引用类型变量的值是一个地址。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。在这种类型的变量传递给参数的时候:会将变量值(引用地址)copy一份,传递给函数作为实参。也就是说:传递给函数的变量所指向的空间,与函数实参所指向的空间是相同的。因此,在函数中通过实参去改变对象的内容,会影响到函数外部变量所指向的对象的内容,因为它们都指向同一个对象。
18、数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length 的属性。String中通过length方法获取字符串长度。集合如List通过size()方法获取集合的大小。
19、String s = new String("xyz");创建了几个字符串对象?
一个或者两个。如果在常量池中没有“xyz”的话,就会在常量池中创建一个"xyz"对象,另外面一个是用new创建在堆上的对象;如果在常量池中有“xyz”的话,则在堆上创建一个对象s,指向常量池中的“xyz”。 扩展:(字符串常量池)字符串常量池是存储在 Java 堆内存中的字符串池,是为防止每次新建字符串带的时间和空间消耗的一种解决方案。在创建字符串时 JVM 会首先检查字符串常量池,如果字符串已经存在池中,就返回池中的实例引用,如果字符串不在池中,就会实例化一个字符串放到池中并把当前引用指向该字符串。
20、(String) 如下程序的输出结果是?
public class StringTest {    public static void main(String[] args) {        String s1 = "Hello," + "word!";        String s2 = "Hello,word!";        String s3 = new String(s1);        String s4 = "Hello,";        s4+="word!";        System.out.println(s1 == s2);  // true        System.out.println(s1 == s3);  // false        System.out.println(s1 == s4);  // false        System.out.println(s2 == s3);  // false        System.out.println(s2 == s4);  // false        System.out.println(s3 == s4);  // false    }}
String s1 = “Hello,”+”word!”;会被JVM优化为String s1 = “Hello,word!”,存贮在字符串常量池中,而s2的内容与s1相同,所以s1与s2都指向常量池中的”Hello,word!”;而s3是通过new关键字创建出来的,s3的地址在堆上,s3的字符串内容在常量池已经有,指向常量池中的“Hello,word!”。s4+=“word!”的过程相当于将原有的s4变量指向的对象内容取出与“word!”作字符串相加操作在存进另一个新的String对象中,在让s4变量指向新生成的对象。 扩展:String s="abc";形式赋值在java中叫直接量,它是在常量池中而不是像使用new关键字一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abc"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指向了同一对象,如果没有,则在常量池中新创建一个"abc",下一次如果有String s1 = "abc";又会将s1指向"abc"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.而String s = new String("abc");和其它任何对象一样.每调用一次就重新分配内存空间产生一个对象。简单的来说: String str = "abc"; 先在内存中找是不是有"hello"这个对象,如果有,就让str指向那个"abc".如果内存里没有"abc",就创建一个新的对象保存"abc"。  1a7609179f025bff2a00f9e023a6bc84.gif

是新朋友吗?记得先点蓝字关注我哦

  后台回复【福利】可查看小编为大家准备的资源。

  后台回复【福利|面试题】即可获取面试题PDF文件。

  后台回复【福利|电子书】即可获取Java电子书。

  论文答辩PPT可查看历史文章,留言召集好友点赞以后可以获得

6d8b5f84b89c53f6f75876460c98cf6d.gif c9e06ee91b0b37da4230f2ce206cda22.gif 6d8b5f84b89c53f6f75876460c98cf6d.gif 6d8b5f84b89c53f6f75876460c98cf6d.gif c9e06ee91b0b37da4230f2ce206cda22.gif 6d8b5f84b89c53f6f75876460c98cf6d.gif 7ffdf182dd3c85f04fd198f271957130.png

如有不对之处,欢迎留言

您的建议是我们成长的动力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值