总结每天10问之Java基础2

Java 基础

OOP相关

11、什么是拆装箱?

答:

在理解拆箱和装箱之前需要理解一个概念:基本类型和封装类型,比如int是基本类型,integer是封装类型(包装器类型)。

基本类型其实对应到c++或者直接说内存中的某个数据具体样子。int比integer占的内存小的多,integer的功能比int多得多。

这两者之间jdk为我们提供了一些转换的方式:拆装箱

这是jdk5之后提供的,为的就是让基本类型和jdk封装类型之间能自动转换。这种自动转换也叫自动拆装箱。

在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行:

Integer i = new Integer(10);

在jdk5之后,

Integer i = 10;

其实使用反编译文件查看后可以发现上面的语句被翻译成下面的:

Integer i = Integer.valueOf(10);

这是编译器帮我们做的,这就是自动装箱。

所谓的拆箱就是反过来的过程:

比如:

Integer i1 = 100;
int i5 = i1;

编译器会帮我们翻译成:

Integer i1 = Integer.valueOf(100);
int i5 = i1.intValue();

如上就是自动拆箱装箱。

拓展

我们经常遇到如下面试题:

public static void main(String[] args) {
    Integer i1 = 100;
    Integer i2 = 100;
    Integer i3 = 200;
    Integer i4 = 200;
    System.out.println(i1 == i2);
    System.out.println(i3 == i4);
}

最后的结果是:

true
false

按照自动装箱拆箱的原理不难理解i3,i4是不同的对象,所以是false。但是为什么i1==i2是true,按理说i1和i2也是不同的对象,具体的原理可以点进Integer.valueOf()去看,这里直接说结论:int有缓存,缓存的代码如下:

	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 =
                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.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

从中可以看出,jdk会缓存-128~127之间的整数。每次去执行valueOf的时候都会检查一下int是否在何处里面已经有了,有的话就不会创建新的对象,而是把引用都指到同一个对象;所以i1==i2为true。

Java中的包装类包括:

byte:Byte,short:Short,int:Integer,long:Long,flfloat:Float,double:Double,char:Character ,boolean:Boolean。

12、equals与==的区别

答:

==: 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是

指相同一个对象。比较的是真正意义上的指针操作。

equals:

equals比较的是两个对象是否相等,所有的对象都基础自Object,即使你没声明,编译器也会为你加上。Object有着方法equals,子类需要重写equals方法来为子类做一些业务性上的判断,比如:两个对象是否相等,业务上只需要比较两个对象的所有filed都相同即可,不需要内存地址都相同的;他们可能是不同地方创建的两个对象,但是他们就是相同。

拓展

一般重写equals,也需要重写hashCode,这是为什么呢?

因为:按照一般hashCode()方法的实现来说,相等的对象,它们的hash code一定相等。

hashCode()方法给对象返回一个hash code值。这个方法被用于hash tables,例如HashMap。

  • 在一个Java应用的执行期间,如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode()方法,该方法必须始终如一返回同一个integer。
  • 如果两个对象根据equals(Object)方法是相等的,那么调用二者各自的hashCode()方法必须产生同一个integer结果。
  • 并不要求根据equals(java.lang.Object)方法不相等的两个对象,调用二者各自的hashCode()方法必须产生不同的integer结果。然而,程序员应该意识到对于不同的对象产生不同的integer结果,有可能会提高hash table的性能。

大量的实践表明,由Object类定义的hashCode()方法对于不同的对象返回不同的integer。

在object类中,hashCode定义如下:

public native int hashCode();

Java对象的eqauls方法和hashCode方法是这样规定的:

  • 1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。
  • 2、如果两个对象的hashCode相同,它们并不一定相同。

hashCode的重写还会有助于HashMap,HashSet等集合的检索,所以这点请引起重视,特别是数据量比较大的时候。

有关hashCode和equals更多的知识,请看这里:https://www.cnblogs.com/Qian123/p/5703507.html#_labelTop

hashCode的编写涉及散列算法,可以根据自己的对象特点去实现。

13、java中是值传递引用传递

答:

对于基本数据类型,传递是值的副本,而不是值本身。

对于对象类型,传递是对象的引用,当在一个方法操作操作参数的时候,其实操作的是引用所指向的对象。

14、构造方法能不能显式调用

答:

不能,构造方法其实实际上是我们编译之后的字节码的init方法,我们声明使用那个构造方法之后,由系统调用的。

15、内部类与静态内部类的区别

答:

内部类访问等其实需要通过它的包含类(外部类),它保留了自己和外部类的一个连接。内部类一个很大的优势就是内部类可以继承其它的类,并且可以直接使用包含类(外部类)字段、方法。这是一个变相的多继承。 这也是内部类最后诱人的地方。

静态内部类和其实是嵌套类,好处是组织结构上清晰点。它会切断和包含类(外部类)的连接,使用静态内部类的时候就像使用别的类差不多。这也意味着:

  1. 要创建嵌套类的对象,并不需要其外围类的对象。

2. 不能从嵌套类的对象中访问非静态的外围类对象。

https://www.cnblogs.com/aademeng/articles/6192954.html

16、String、 StringBuffer 和 StringBuilder 的区别是什么?

答:

String内部定义了一个private final byte[] value;,每次修改String其实是新创建一个String,然后将引用修改到新的String,效率比较低。

为了解决上面的问题,JDK提供了StringBuffer和StringBuilder来构建String,这两个构建String的效率比String高。StringBuffer是线程安全的,因为内部实现使用了大量的synchronized。StringBuilder是非线程安全的。

为了获得比较高的性能,我们可以使用ThreadLocal和StringBuilder结合的方式,来创建字符串。

17、String a = new String(“zxc”); 创建了多少个对象。

答:

“zxc”会去字符串常量池看看有没有这个字符串,有就直接返回这个对象,不会创建新的对象,否则就会在常量池创建一个字符串。

然后在堆里面创建一个String对象,字符串赋值给String对象里面的value。

创建一个对象,或者两个对象。

18、String str=”aaa”,与String str=new String(“aaa”)一样吗?

答:

不一样,String str=”aaa” 会把字符串检查在常量池中是否拥有,如果有的话就直接拿常量池的字符串引用关联起赋值的对象,如果不存在就放入常量池,所谓的常量池在jdk8之中放在方法区,再把引用给这个对象。

new String(“aaa”) 是在堆里面之间创建一个字符串对象。String提供了String.intern(),将字符串变量放入线程池。

两者不相同,但是使用equals方法可以判断两个字符串是相等的。

为了更好的理解,可以结合以下代码一起看:

public static void main(String[] args) {
    String s1 = "Hello";
    String s2 = "Hello";
    String s3 = "Hel" + "lo";
    String s4 = "Hel" + new String("lo");
    String s5 = new String("Hello");
    String s6 = s5.intern();
    String s7 = "H";
    String s8 = "ello";
    String s9 = s7 + s8;

    System.out.println(s1 == s2);  // true
    System.out.println(s1 == s3);  // true
    System.out.println(s1 == s4);  // false
    System.out.println(s1 == s9);  // false
    System.out.println(s4 == s5);  // false
    System.out.println(s1 == s6);  // true
}
19、Java的四种引用

答:

强引用:OutOfMemory也不能释放的引用。

弱引用:内存不足的时候,强制回收。

软引用:只要JVM垃圾回收器发现就回收。ThreadLocal就是使用这个。

虚引用:这个和弱引用差不多,只不过回收之前会放入ReferenceQueue,异步回收。

20、Java创建对象有几种方式?

答:

  • new 一个对象
  • 反射
  • clone
  • 反序列化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
一、Java基础语法 1.变量和常量 变量用于存储数据。Java中的变量有三种类型:局部变量、成员变量和静态变量。 常量是指在程序运行时不会被修改的值,在Java中用final关键字标识。常量分为静态常量和实例常量。 2.数据类型 Java中的数据类型分为基本数据类型和引用数据类型。基本数据类型有byte、short、int、long、float、double、char和boolean。 引用数据类型包括类、接口、数组和枚举。 3.运算符 Java中的运算符包括算术运算符、关系运算符、逻辑运算符、位运算符、三目运算符等。 4.流程控制 Java中的流程控制有if-else语句、switch-case语句、for循环、while循环、do-while循环、break语句、continue语句等。 二、面向对象编程 1.类和对象 类是对象的实体,包含属性和方法。对象是类的实例,具有独立的状态和行为。 2.继承和多态 继承是指一个类可以继承另一个类的属性和方法。 多态是指同一种操作作用于不同的对象,可以有不同的实现方式,实现方式由实际的对象类型决定。 3.封装和抽象 封装是指将类的属性和方法进行隐藏,只对外暴露必要的接口。通过封装可以保证类的安全性和灵活性。 抽象是指将类的共性进行概括,并去除与具体实现无关的内容。通过抽象可以提高代码的复用性和可维护性。 三、异常处理 在Java中,异常是指程序执行时发生的错误或异常情况。Java中的异常处理机制可以有效地避免程序运行中的错误导致程序崩溃。 Java中异常处理机制可以通过try-catch语句捕获异常,并通过throw和throws语句抛出和传递异常。在异常处理中可以利用finally语句完成清理工作。 四、集合框架 Java中的集合框架是对容器类的统称,包括List、Set和Map等容器类。 List是一个有序的容器,允许重复的元素。Set是一个无序的容器,不允许重复的元素。Map是一种键值对的映射容器。 五、IO操作 Java中的IO操作包括字节流和字符流。字节流操作的是二进制数据,字符流操作的是文本数据。 Java中的IO操作可以通过输入流和输出流来实现。输入流用于读取数据,输出流用于写入数据。 六、线程 线程是指程序中的一个执行流程,一个程序可以同时运行多个线程执行不同的任务。 在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。 Java中的线程可以通过synchronized关键字来实现同步,防止线程间数据的冲突。 七、JDBC数据库操作 JDBC是Java数据库连接的一种标准,可以用于连接关系型数据库的操作。使用JDBC需要进行数据库驱动的加载,然后进行数据库连接,最后进行数据库的增删改查等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值