【Java】类和对象2

简介: 【Java】类和对象

5.对象的构造及初始化

5.1 如何初始化对象

我们知道局部变量必须先赋值在使用,如果不赋值直接使用则会编译失败 。


对于实例化对象来说如果不初始化成员变量,成员变量里面存放的是默认值。


①局部变量先赋值后使用,则编译成功

饿.png



②局部变量不赋值直接使用,则编译失败

の.png



③上面我们讲了对于实例化对象来说如果不初始化成员变量,成员变量里面存放的是默认值


class Data {
    public int year;
    public int month;
    public int day;
    public void print() {
        System.out.println(year+"-"+month+"-"+day);
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data();
        data.print();
    }
}

运行结果:


呃.png


那么现在就出现了两个问题:


那对象究竟如何初始化?

为什么局部变量必须先赋值后使用,而对象中的成员变量就不需要赋值可以直接使用?

注:实例化对象里面存的就是成员变量,初始化也就是对成员变量进行初始化


那接下来我们就带着以上两个问题进入构造方法的学习


5.2 构造方法

1.概念


构造方法的概念:构造方法又称为构造器,它是一个特殊的成员方法,名字必须要与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次  


2.特性


它是一个特殊的成员方法

没有返回值类型,设置为void也不行

名字与类名相同

一般情况下使用public修饰

创建对象的时候编译器自动调用,且在整个对象的生命周期内只会调用一次

构造方法可以重载

class Data {
    public int year;
    public int month;
    public int day;
    public Data(int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("编译器自动调用了构造方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data(2022,9,10);
    }
}

运行结果:


(⊙﹏⊙).png


上述代码中主方法里面就只有一条实例化 Data 类的语句,通过实例化语句编译器自动调用了对象构造方法,并在构造方法中给成员变量初始化了


注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。开辟空间是实例化的时候开辟的也就是new的时候开辟的


3.构造方法的重载


构造方法可以重载:


class Data {
    public int year;
    public int month;
    public int day;
    public Data() {
        System.out.println("编译器自动调用了没有形参的构造方法");
    }
    public Data(int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
        System.out.println("编译器自动调用了有形参的构造方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data(2022,9,10);
        Data data1 = new Data();
    }
}


运行结果:

啊.png



上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载


当构造方法重载时,根据实例化对象后面的参数进行匹配构造方法


4.编译器什么时候自动生成一个无参的构造方法


如果用户没有自己定义构造方法,那么编译器将会自动生成一份默认无参的构造方法:


class Data {
    public int year;
    public int month;
    public int day;
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data();
    }
}

我们看不到编译器自动生成的构造方法,但是不代表它没有生成


如果用户自己定义了一个构造方法那么,编译器将不会自动生成:


嗄.png


运行结果:

吖.png



我们说如果用户不自己定义一个构造方法,那么编译器将会自动生成一个无参构造方法。上述代码自定义了一个有参的构造方法,那么编译器将不会自动生成了,所以当 data1 在编译时就直接报错了,原因就是用户自定义了一个有参的构造方法,编译器无法自动生成一个无参的构造方法了,如果想解决这个问题那么用户在定义一个无参的构造方法即可


5. 构造方法中,可以通过 this 调用其他构造方法来简化代码


class Data {
    public int year;
    public int month;
    public int day;
    public Data() {
        this(2022,9,10);
    }
    public Data(int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public void print() {
        System.out.println(year+"-"+month+"-"+day);
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data();
        data.print();
    }
}

运行结果:


阿.png


this(...)必须在构造方法中的第一条

不能形成环

不能形成环:不能在无参构造方法中调用有参构造方法,在有参构造方法中调用无参构造方法 ,这样就容易形成环


锕.png


6.默认初始化


学习了上面的构造方法我们也就解决了第一个问题,就是对象如何初始化。


那我们接下来看第二个问题, 为什么局部变量必须先赋值后使用,而对象中的成员变量就不需要赋值可以直接使用?


要搞清楚第二个问题,就要了解 new 关键字背后所发生的一些事情


Data data = new Data();

在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍一下:


检测对象对应的类是否加载了,如果没有加载则加载

为对象分配内存空间

处理并发安全问题。比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突

初始化所分配的空间

是.png


设置对象头信息

调用构造方法,给对象中各个成员赋值

所以总结下来,为什么对象中的成员变量就不需要赋值可以直接使用,因为它调用了构造方法完成了初始化


7.就地初始化


class Data {
    public int year = 2022;
    public int month = 9;
    public int day = 10;
    public void print() {
        System.out.println(year+"-"+month+"-"+day);
    }
}
public class Test {
    public static void main(String[] args) {
        Data data = new Data();
        data.print();
    }
}

在声明成员变量时,就直接给出了初始值,就叫做就地初始化


相关文章
|
4天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
24天前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
21天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
42 17
|
13天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
17天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
58 4
|
28天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
46 17
|
18天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
36 2
|
22天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
26天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
26天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
下一篇
无影云桌面