【java】学习笔记3(三大特殊类:String,Object,包装类)

1️⃣String类

理解字符串的不可变性。
源码:

  1. 内部存储数据的value字符数组对外不可见,外部无法直接使用;且被final修饰,无法修改内容,字符串字面值直接赋值常量池。
  2. final修饰的类,无法继承,确保所有JDK程序员使用的都是同一个类,保证规范性。

更多关于String的内容
👇
认识String类(特性和常用方法)

2️⃣Object类

1.Object类是所有类的默认父类(不需要使用extends显示继承),因此Object类的所有方法(private除外),所有类的对象都能使用。

我们来看看Object源码的结构:
在这里插入图片描述
toString()方法

能将任意对象转为字符串输出,打印对象内容,System.out.println()接收任意对象并输出,默认调用的就是toString()

class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args){
        Student student = new Student("张三",40);
        System.out.println(student);
    }
}

想要输出具体内容,就需要覆写toString

@Override
public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}

输出结果:

equals()方法

想要比较两个对象是否相等(一般比较属性),需覆写equals方法。
默认的==会比较当前对象(this表示当前对象的引用)与传入的对象地址是否相等。

class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args){
        Student student = new Student("张三",40);
        Student student1 = student;
        Student student2 = new Student("张三",40);
        System.out.println(student.equals(student1));
        System.out.println(student.equals(student2));
    }
}
//输出结果;
true
false

此时 Student 类默认使用的 Object 提供的 equals 方法,student 和 student1 都是对象的引用,指向同一片内存空间,所以返回 true 虽然 student 和 student2 的属性值相等,但是他俩的地址不同,所以返回 false。

若需要让 Student 类的 equals 按属性值比较,得要覆写 equals 方法:

    // 当前对象和传入的obj相比
    public boolean equals(Object obj) {
        // 1.判断obj是否为空
        if (obj == null) {
            return false;
        }
        // 2.判断obj是否就是自己
        if (obj == this) {
            return true;
        }
        // 3.判断obj是否是Student类的对象
        //instanceof可以判定一个引用是否是某个类的实例
        if (!(obj instanceof Student)) {
            return false;
        }
        // 4.obj一定是Student类的对象而且与当前对象不是一个地址
        // 向下转型还原为Student,比较当前对象的属性和传入对象的属性
        Student stu = (Student) obj;
        return this.name.equals(stu.name) && this.age == stu.age;
    }

2.Object不仅是所有类的父类,而且只要是引用数据类型,都可以向上转型变为ObjectObject类型可以接收所有引用数据类型,包括数组和接口。

class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
interface IMessage{
    void print();
}
class MessageImpl implements IMessage{

    @Override
    public void print() {
        System.out.println("hello");
    }
}

public class ObjectTest {
    public static void main(String[] args){
        //自定义类型
        Object obj1 = new Student("张三",40);
        //字符串
        Object obj2 = "hello";
        //顺序表
        Object obj3 = new ArrayList<>();
        //数组引用
        int[] data = new int[]{3,2,5,8,4,7,6,9};
        //接口引用
        IMessage msg = new MessageImpl();
        Object obj4 = data;
        Object obj5 = msg;
        int[] ret = (int[])obj4;
        IMessage imsg = (IMessage) obj5;
        System.out.println(Arrays.toString(ret));
        imsg.print();
    }
}

//输出结果:
[3, 2, 5, 8, 4, 7, 6, 9]
hello

Object是引用数据类型的最高参数统一化,如果设计的方法需要接收所有引用类型,那就把类型声明为Object

3️⃣包装类

1.基本类型和包装类

Object引用可以指向任意类型的对象,但有例外出现了,8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?
实际上也确实如此,为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

基本就是类型的首字母大写,除了IntegerCharacter

自己实现的包装类

class MyInterger{
    //保存具体的整形值
    private int data;
    public MyInterger(int data){
        this.data = data;
    }
    public int intValue(){
        return this.data;
    }
}
public class IntDemo {
    public static void main(String[] args) {
    	//使用JDK内置的包装类
    	//将int->类
        Integer demo = new Integer(10);
        int data = demo.intValue() + 1;
        System.out.println(data);
        //自己实现
        MyInterger demo = new MyInterger(10);
        int data = demo.intValue() + 1;
        System.out.println(data);
    }
}

//输出结果:
11

2.装箱和拆箱

int i = 10;
// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
Integer ii = Integer.valueOf(i);
Integer ij = new Integer(i);
// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
int j = ii.intValue();

3.自动拆装箱

可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

int i = 10;

Integer ii = i; // 自动装箱
Integer ij = (Integer)i; // 自动装箱

int j = ii; // 自动拆箱
int k = (int)ii; // 自动拆箱

在用法上上,包装类和基本类型没啥不同,但是在一些细节处有区别:

🅰️对于基本类型,其默认值是数值0,对于包装类而言,默认值是null

public class IntDemo {
    private int a;
    private Integer b;
    public static void main(String[] args) {
        IntDemo demo = new IntDemo();
        System.out.println(demo.a);
        System.out.println(demo.b);
    }
}
//输出结果:
0
null

那么到底什么时候用基本类型,什么时候用包装类呢?

阿里编码规约:

  1. 在类中定义成员变量,必须使用包装类声明
    原因:在开发一个银行卡系统中,肯定会有用户的卡号和余额(浮点数)
    double balance;默认值是0.0,那么是正常使用下的余额为0.0,还是用户已经注销了设置的呢?
    Double balance;默认是null ,此时和默认值0.0就不同了,便可以将余额清0和帐号注销两种情况区分开来。
    将来把类的成员变量存储到数据库中,默认值经常造成干扰。利用null来判断是否存在数值。
  2. 方法中大量进行算术运算时,使用基本类型

🅱️关于包装类的对象比较使用eqauls!!!

包装类使用==是比较两个包装类对象的地址是否相等!!需要比较值用eqauls

对于包装类而言(以int为例),自动装箱时,JVM会创建一个缓存处理。
对于[-128,127]的取值,Integer会缓存对象(String常量池)
例如:

4.包装类和String

🅰️包装类->String

Integer i1 = 10;
String str1 = String.valueOf(i1);
System.out.println(str1);

//输出结果:
10

🅱️String->包装类

String str2 = "123";
Integer i2 = Integer.parseInt(str2);
System.out.println(i2);

//输出结果:
123

注意字符串中不要包含处数字外的其他字符,否则会报异常

5.编译期的自动拆装箱

可以使用反编译工具来查看下自动装箱和自动拆箱过程,并且看到这个过程是发生在编译期间的。

javap -c 类名称
Compiled from "Main.java"
public class Main {
public Main();
	Code:
		0: aload_0
		1: invokespecial #1 // Method java/lang/Object."<init>":()V
		4: return
public static void main(java.lang.String[]);
	Code:
		0: bipush 10
		2: istore_1
		3: iload_1
		4: invokestatic #2 // Method java/lang/Integer.valueOf:
(I)Ljava/lang/Integer;
		7: astore_2
		8: iload_1
		9: invokestatic #2 // Method java/lang/Integer.valueOf:
(I)Ljava/lang/Integer;
		12: astore_3
		13: aload_2
		14: invokevirtual #3 // Method java/lang/Integer.intValue:()I
		17: istore 4
		19: aload_2
		20: invokevirtual #3 // Method java/lang/Integer.intValue:()I
		23: istore 5
		25: return
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bruin_du

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值