12.常用类之包装类

本文深入探讨Java中包装类的定义、作用、构造方法、转换及特点,并详细解析String类的特性,包括常量池、引用存储、编译与运行期创建区别,以及常见面试题解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实用类

1.包装类

1.1 定义

  • 包装类是把基本类型转换为对象,是引用类型

1.2作用

  • 包装类可以有很多操作的方法
  • 之前我们学习的集合比如add(1)在底层中会转换成包装类型integer类型插入到集合容器中,集合里面插入的都是引用类型。

1.3 包装类型继承关系图

在这里插入图片描述

1.4 构造方法创建包装类型

  1. 在构造方法中可以将与之对应的基本数据类型作为构造方法参数,来创建包装类的对象

  2. charcater除外,在构造方法中可将对应的基本类型以字符串类型作为构造方法参数,来创建包装类的对象

    /**
     * 	以构造方法创建包装类型对象
     * @author Administrator
     *
     */
    public class Test {
    	public static void main(String[] args) {
    		Integer i = new Integer(1000);
    		System.out.println(i.MIN_VALUE);
    		System.out.println(i.MAX_VALUE);
    		Integer i2 = new Integer("2000");
    		System.out.println(i2);
    		
    		//方式1:以基本类型为构造方法的参数创建包装类型对象
    		Double d = new Double(98.7);
    		Boolean b = new Boolean(true);
    		Float f = new Float(87.4);
    		Character c = new Character('男');
    		
    		//方式2:以字符串形式创建包装类型对象
    		Double d2 = new Double("98.7");
    		Boolean b2 = new Boolean("true");
    		Float f2 = new Float("87.4");
    //		Character c2 = new Character("男");//character只能是字符类型
    		
    		//方式3:自动装箱 可以把基本类型直接赋给包装类型对象,底层自动实现
    		int a = 3;
    		Integer a2 = a;
    		Integer a3 = 100;
    		System.out.println(a2+" " +a3);
    	}
    }/**
     * 	以构造方法创建包装类型对象
     * @author Administrator
     *
     */
    public class Test {
    	public static void main(String[] args) {
    		Integer i = new Integer(1000);
    		System.out.println(i.MIN_VALUE);
    		System.out.println(i.MAX_VALUE);
    		Integer i2 = new Integer("2000");
    		System.out.println(i2);
    		
    		//方式1:以基本类型为构造方法的参数创建包装类型对象
    		Double d = new Double(98.7);
    		Boolean b = new Boolean(true);
    		Float f = new Float(87.4);
    		Character c = new Character('男');
    		
    		//方式2:以字符串形式创建包装类型对象
    		Double d2 = new Double("98.7");
    		Boolean b2 = new Boolean("true");
    		Float f2 = new Float("87.4");
    //		Character c2 = new Character("男");//character只能是字符类型
    		
    		//方式3:自动装箱 可以把基本类型直接赋给包装类型对象,底层自动实现
    		int a = 3;
    		Integer a2 = a;
    		Integer a3 = 100;
    		System.out.println(a2+" " +a3);
    	}
    }
    

1.5 valueof()方法创建包装类型

/**
 * 	通过valueof()方法创建包装类型对象
 * @author Administrator
 *
 */
public class Test2 {
	public static void main(String[] args) {
		Integer invalue = Integer.valueOf(21);
		Integer invalue2 = Integer.valueOf("21");
		System.out.println(invalue);
		System.out.println(invalue2);
		
		//方式1:以基本类型为参数类型创建包装类型对象
		Double d1 = Double.valueOf(98.7);
		Boolean b1 = Boolean.valueOf(true);
		Float f1 = Float.valueOf(77.8f);
		
		//方式2:以字符串为参数类型创建包装类型对象
		Double d2 = Double.valueOf("98.7");
		Boolean b2 = Boolean.valueOf("true");
		Float f2 = Float.valueOf("77.8");
		Character c2 = Character.valueOf('男');
		
	}
}

1.6 xxxValue()方法将包装类型转换成基本类型

public class Test3 {
	public static void main(String[] args) {
		Integer i = new Integer(1000);
		int intValue = i.intValue();
		System.out.println(intValue);
		
		Double d = new Double(99.9);
		double doublevalue = d.doubleValue();
		
		Integer i1 = 2000;
		int i2 = i1;//拆箱:把包装类型自动转换成了基本类型
	}
}

1.7 拆箱和装箱

  1. 装箱:把基本类型转换成包装类型

    Integer i1 = 2000;
    
  2. 拆箱:把包装类型转换成基本类型

    Integer i1 = new Integer(1100);
    int i2 = i1;//拆箱:把包装类型自动转换成了基本类型
    

1.8 总结包装类的特点

  1. 所有的包装类型都是final类型,不能被继承
  2. java5之后,允许基本类型和包装类型进行混合运算
  3. 包装类是引用类型存储在堆内存里面,基本类型是存储在栈内存里面,由于存储简单的值存储在栈内存效率更快,但是在基本类型需要用到对象的时候或者调用方法的时候需要使用到包装类

2.String类详解

2.1 内容一:

  • 注意:String不是一个基本数据类型

  • String是一个特殊的包装类型,之前我们其他的包装类都是需要Integer i= new Integer()来创建,是保存在堆内存里面的。

    可以String str = new string();来创建
    也可以string str2 = "abc";来创建
    
  • 关于==String str2 = “abc”;==java内部将此语句转换分为几个步骤:

    1. 先定义一个名为str2的对string类的对象的引用变量存入栈中
    2. 在常量池中查找是否存在内容为"abc"的字符串对象
    3. 如果不存在则在常量池中创建"abc",并让str2引用对象
    4. 如果存在则直接让str2引用该对象
  • 代码验证

    public class Test {
    	public static void main(String[] args) {
    		String str1 = "abc";
    		String str2 = "abc";
    		//==用于比较两个字符串的地址,equals是判断两个字符串的值是否相等
    		System.out.println(str1==str2);//true
    				
    	}
    }
    

2.2 内容二:

  • 常量池

    • 常量池用于存放字符串常量和基本类型常量

    • 常量池的好处是为了避免频繁的创建和销毁对象而影响性能,其实现类对象的共享。

    • 比如字符串常量池,在编译阶段就把使用的字符串文字放到一个常量池中,

    • 优势:1.节约内存空间

      如:

      String str1 = "abcd";
      String Str2 = "ab" +"cd";
      //str2是在编译阶段优势为"abcd",在去判断常量池是否"abcd",有就把常量池地址也指引给str2,所以str1和str2共享地址,节约资源
      System.out.println(str1==str2);//true
      
    • 2.节省运行时间,字符串比较有两种方式:

      1. == 比较是两个字符串的地址,用于判断引用是否是同一个地址,如果是同一个地址那么值肯定相等

      2. equals()方法比较,如果不是同一个地址那么就去比较字符串之间的值

        	public boolean equals(Object anObject) {
                if (this == anObject) {
                    return true;
                }
                if (anObject instanceof String) {
                    String anotherString = (String)anObject;
                    int n = value.length;
                    if (n == anotherString.value.length) {
                        char v1[] = value;
                        char v2[] = anotherString.value;
                        int i = 0;
                        while (n-- != 0) {
                            if (v1[i] != v2[i])
                                return false;
                            i++;
                        }
                        return true;
                    }
                }
                return false;
            }
        

2.3 面试题1:

String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2);//true
  1. 第一次创建String str1=“abc”;的时候,先在常量池判断有没有“abc”,如果没有就在常量池中创建"abc"然后将常量池的引用地址赋给在栈内存开辟的str1(str1是在常量池中“abc“的引用)
  2. 第二次创建String str2=“abc”;的时候也先判断常量池有没有“abc”,如果有就不需要在常量池再次创建“abc”,可以将已经创建好了的"abc"指引赋给str2;
  3. 因此str1==str2去比较两个指引的地址的时候,是指向了同一个地址,所以返回true

在这里插入图片描述

2.4 面试题2

String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
System.out.println(str1+" "+str2);//bcd abc
System.out.println(str1==str2);//false

在这里插入图片描述

2.5 面试题3

String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
String str3 = str1;
String str4 = "bcd";
System.out.println(str1==str4);//true
System.out.println(str1==str3);//true

在这里插入图片描述

2.6 面试题4

  • 然后我们在来看看String str = new String(“abc”);创建的过程

    1. 先定义一个名为str的对String类的对象引用变量放入栈中
    2. 然后在堆中(不是常量池)创建一个指定的对象,并让str引用指向该堆内存中存储的对象
    3. 在常量池中查找是否存在内容是"abc"的字符串对象
    4. 如果不存在,则在常量池中创建内容为"abc"的字符串对象,并将堆中的对象与之关联起来
    5. 如果存在,则将堆内存中new出来的字符串对象与常量池中的对象关联起来
  • 代码示例

    String str1 = new String("abc");
    String str2 = new String("abc");
    String str3 = "abc";
    System.out.println(str1==str2);//false
    //在堆内存创建了两个地址,返回false
    System.out.println(str1==str3);//false
    //创建了两个引用,两个引用分别指向堆内存的地址和常量池中的地址,地址不同返回false
    
  • 如图

在这里插入图片描述

2.7 面试题5

public class Test4 {
	public static void main(String[] args) {
		String str1 = "abc";
		String str2 = new String("abc");
		String str3 = str2.intern();//intern方法用于获取堆内存中指引到常量池中的"abc"
		System.out.println(str1==str2);//false
		System.out.println(str1==str3);//true
	}
}

在这里插入图片描述

2.8 总结

  1. 对于字符串,其对象的引用都是存储在栈内存中的
  2. 如果是编译期间已经创建好的(直接用""定义的String str2 = “abc”;)就存储在常量池中
  3. 如果是运行期(new String(“abc”);)才能确定到存储在堆中
  4. 在常量池中数据会共享,常量池只有一份;在堆中有多份,数据不共享

最常见的面试题

问题:String s = new String(“abc”);产生了几个对象?

答:一个或者两个,如果常量池有"abc"就是创建一个,常量池没有"abc"就需要创建两个。

注意:

  • 基本数据况的包装类都是final修饰的,值都不可以被改变,不仅仅是String类的值不可修改,所有的基本类型的包装类都不能更改其内部的值。

2.8 总结

  1. 对于字符串,其对象的引用都是存储在栈内存中的
  2. 如果是编译期间已经创建好的(直接用""定义的String str2 = “abc”;)就存储在常量池中
  3. 如果是运行期(new String(“abc”);)才能确定到存储在堆中
  4. 在常量池中数据会共享,常量池只有一份;在堆中有多份,数据不共享

最常见的面试题

问题:String s = new String(“abc”);产生了几个对象?

答:一个或者两个,如果常量池有"abc"就是创建一个,常量池没有"abc"就需要创建两个。

注意:

  • 基本数据况的包装类都是final修饰的,值都不可以被改变,不仅仅是String类的值不可修改,所有的基本类型的包装类都不能更改其内部的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值