杂-Java-1

杂-Java-1

捡破烂的诗人 620 2022-07-10
  • 联系方式:1761430646@qq.com
  • 菜狗摸索,有误勿喷,烦请联系

1. ==和equals的区别

1.1 ==

  • A== B
  • 如果比较的是基本数据类型,int ,double,则比较的是它们的值
  • 如果比较的是对象,则比较它们所指向的内存地址是否相同

==的对象比较特点

  • 这里的字符串==比较特殊

    • 如果字符串是直接赋值,按常量方式相比

    ==的字符串

    • 如果字符串是new出来的

    ==的对象比较

    Snipaste_2021-10-04_21-36-52

  • Snipaste_2021-10-04_21-37-50

    • a + b底层调用的是StringBuilder的拼接相当于在堆中创建了一个字符串对象c指向的是字符串常量池中的“abc”,而d指向的是堆中有的一个值为“abc”的字符串对象,所以它们指向的内存地址不同

1.2 equals

  • A.equals(B)
  • 只能比较引用类型
  • 要看要比较的类有没有重写父类Object的equals方法
    • 如果没有,A.equals(B)等同于 == ,相当于比较内存地址
    • 如果有,则按照重写的equals方法的比较方式来比较

equals比较特点

2. 常量,对象转化成字符串

2.1 XX.toString()

  • 这是Java的Object类拥有的方法,其子类都可以调用

  • 默认情况下调用Object的toString()方法,返回全限定类名 + @ + 地址

    Object的toString

    • 子类可以重写此方法,返回一个我们所需要的固定形式的字符串
  • 任意不为null的对象都可以调用此方法,如果对象为null,会空指针异常

2.2 String.valueOf(XXX)

  • 这是String类的静态方法

    • 如果参数传入的是基本类型,那么返回的字符串与参数长得一模一样
    • 如果参数传入的是null,那么会返回字符串“null”
    • 如果参数传入的是非null对象,那么会调用对象的toString()方法返回其值

    String的valueOf方法

  • 推荐使用

2.3 (String)

  • 这是强制转换

  • 基本类型不可以强转,编译时就会报错

    String强转

  • 被强转对象必须需要注意的是类型必须能转成String类型,否则强转异常

    String强转代码

    • null是可以强转为任何Java类型的

3. private

  1. 都知道被private修饰的成员或方法,无法被外部访问
  2. 但是Java可以通过反射机制来设置其menthod.setAccessible(ture)或者.filed.setAccessible(ture)来强行访问
  3. 那么此时private就失去了它的作用?
  4. 不是,private有它自己的意义
    • 它不是为了绝对安全设计的,而是对常规使用Java的一种规范,比如网吧内未成年禁止入内,但实际上的情况大家都知道

4. Java的boolean型占多大内存?

  1. 在Java规范中,并没有明确指出boolean的大小,即它的“大小”并不是精确定义的,下面官方文档的说明

    boolean-大小未定义

  2. 在《Java虚拟机规范中》,Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素占8位

  3. 也就是可以理解为boolean类型占4个字节,和boolean数组中的元素占一个字节,但是这是要建立在虚拟机实现按照规范来的,

  4. 所以boolean类型占多大内存具体还要看虚拟机是否按照规范来,1个字节,4个字节都是有可能的–运算效率和存储空间之间的博弈

5. 为什么重写 equals 时为什么一定要重写 hashCode?

  • **equals方法和hashCode方法时Object类中的两个基础方法,它们共同协作来判断两个对象是否相等。**而这样设计的目的在于性能

  • 在HashMap中,我们知道当我们要查询某个键值对时,通过是通过key的hashCode值传给hash()方法接着再去求得此键值对所在的桶的位置。

    • 试想一下,要是没有hashCode方法,那么当我们想查某个键值对时,必须一个一个遍历HashMap中的元素,这样无疑性能很低
  • 而对于比较两个对象是否相等时,我们通常先比较其hashCode值相同,如果相同的话再使用equals方法取判断是否为同一对象,如果为true,那么这两个对象就是相等的,否则其他任何情况都认为这两个对象不相等。

    • 为什么不直接使用hashCode方法就确定这两个对象是否相等呢?

      • 在程序的某次执行过程中,某一对象多次调用hashCode方法返回的值一定相同,而对于不同对象,通常是不同的,但是也是有机会会相同的
      • 所以hashCode值相同的两个对象,实际上是有可能不同的
      • 使用hashCode可以起到快速初次判断对象是否相等的作用
    • 为什么不直接使用equals()方法就确定这两个对象是否相等呢?

      • 对于Object类的equals方法,是去比较两个对象的地址是否相同
      • 如果我们的自定义子类没有重写这个equals方法,那么我们不管实例化多少个不同的子类,他们调用equals方法都不可能返回true,因为每次实例化时,尽管其内部属性一模一样,但是还是属于指向不同的地址
      • 所以自定义子类时要重写equals方法,根据我们自己的业务需求自定义如果判断什么情况时相等。
      • 当自定义重写了equals方法时,我们就可以使用其两个实例对象判断是为相同了,那么其实不用hashCdoe()方法了,那么为毛还要重写hashCode方法了,其实这个问题就回到了上面的大问题上

6. 接口和抽象类的区别

  1. 类型扩展不同:抽象类是单继承,而接口是多继承
  2. 方法访问控制符:抽象类无限制,只是抽象类中的抽象方法不能被private修饰;而接口有限制,接口默认的是public控制符
  3. 属性方法控制符:抽象类无限制,而接口有限制,接口默认的是public static final
  4. 方法实现不同:抽象类中的普通方法必须有实现,抽象方法必须没有实现;而接口中普通方法不能有实现,但在JDK8中的static和default方法必须有实现
  5. 静态代码块的使用不同:抽象类可以有静态代码块,而接口不能有
  6. 子类不能重写接口中static修饰的方法,就算父子有一样的static方法,也是属于不同的两个方法

7. ConcurrentHashMap不允许插入null

  • HashMap是允许插入null值的,因为它是单线程的,可以通过调用方法containsKey()来具体判断返回的NULL值是不存在还是实际上插入的就是NULL值
  • 而ConcurrentHashMap或Hashtable是不允许给key或value插入null值的,因为它是多线程的,会造成二义性:1.值没有在集合中,所以返回存在null;2. 值就是null,所以返回的就是它原本的null值
    • 多线程不允许是因为举个例子:当某个时刻,我们查到的null值代表本身不存在作为结果返回,但是同时有个线程插入了一个同一个key,值为null的键值对,此时含义为本身值就位null,但是我们拿到的结果的null的含义就改变了,区分不了到底是哪个意思,造成了二义性。

8.int,new Integer(), Integer比较区别

8.1 基本区分

  • int是Java的一种基本类型,而Integer对象的引用,是int的包装类
  • int默认值为0,而Integer默认值为null
  • int是直接存储数据值,Integer则是生成一个指针指向此对象

8.2 两个new Integer()的比较–永远为false

  • ==号对象之间比较的是内存地址,基本数据类型比较的是数值大小

  • 由于不同对象指向不同的内存地址,所以一直为false

    8.1

8.3 两个(使用自动装箱生成的)Integer变量比较

  • 结论:

    • 如果两个变量值均在在-128 ~ 127之间,则比较结果为true,否则为false
  • 理由:

    • Integer i = 100的底层实际上是Integer i = Integer.valueOf(100),而在Integer类中有个缓存数组,其值范围为-128 ~127,当调用Integer.valueOf()方法时,如果参数值在这个范围内,则立马返回此缓存数组中对应的指引,否则new Integer()出来
    • 8.2

    8.3

8.4 Integer变量(自动装箱)和new Integer()变量比较

  • 结论:永远不相等
  • 理由
    • 从上述可知,Integer i = xxx实际上所引用的对象要不是重新new出来,要不是就是指向Java常量池中的,而正常的new Integer()是在堆中新建的对象,两者在内存中的地址不同

8.5 int变量和Integer、new Integer()比较

  • 结论:只要两个的数值是相等的,则为true,否则为false
  • 理由:
    • 当包装类Integer和基本数据类型int比较时,Java会自动拆箱为int,然后进行数值上的比较

# Java # 杂