Java类和对象🎉🎉🎉写在前面:
博主主页:🌹🌹🌹戳一戳,欢迎大佬指点!
博主秋秋:QQ:1477649017 欢迎志同道合的朋友一起加油喔💪
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个小菜鸟嘿嘿
-----------------------------谢谢你这么帅气美丽还给我点赞!比个心-----------------------------
- 🌈七,构造方法
- 🌟7.1,构造方法的概念
- 🌟7.2,构造方法的特性
- 🌈八,代码块
- 🌟8.1,代码块的概念及其分类
- 🌟8.2,构造代码块(实例代码块)
- 🌟8.3,静态代码块
- 🌟8.4,实例代码块与静态代码块的初始化循序
首先在进入构造方法之前,先问大家一个问题:大家觉得一个对象的产生需要几步,具体过程?
答案是会经过两步:
🌕1,为对象分配内存空间。
🌕2,调用合适的构造方法
这里就提到了构造方法,那到底什么是构造方法,下面会做详细的介绍:
🌟7.1,构造方法的概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
当我们在new对象的时候,就会调用构造方法,当我们没有提供构造方法的时候,编译器会自动提供一个没有参数的构造方法。注意,构造方法的作用仅仅是为了构造对象,不负责分配空间。
🌟7.2,构造方法的特性
🌕1,在定义构造方法的时候,方法名必须和类名相同。
🌕2,构造方法是没有返回值的,设置为void也不行,简单点说就是不写。
🌕3,在创建对象的时候会自动调用构造方法,并且在对象的生命周期内只会调用一次。
🌕4,构造方法是可以重载的,这也就是为什么说在创建对象的时候会调用合适的构造方法,因为可能存在多个参数不同的构造方法。
class Person{
private String name;
private int age;
public Person(){
System.out.println("Person<> init");
}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("Person init" );
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TestDemo220507 {
public static void main(String[] args) {
Person per1 = new Person();//它会去调用无参的那个构造方法
System.out.println(per1);
System.out.println("=========================");
Person per2 = new Person("xiaowang",20);//它会去调用有参的那个构造方法
System.out.println(per2);
}
}
程序运行截图:
所以说呢,在实例化对象的时候,我们会调用构造方法,并且也是可以传参的,根据参数的不同,我们在实例化对象的时候只会调用相应的构造方法。
🌕5,如果说用户没有自己定义构造方法,那么我们在实例化对象的时候编译器会自动生成构造方法并且调用,但是记住,这个默认的构造方法一定是无参的。
🚩注意:这里有特别注意的一个点,就是一旦用户自己定义了,那么编译器就不会自动生成了。因为编译器只能是自动生成无参的,但是特别怕的是我们自己定义了一个有参构造方法,这个时候如果我们想去定义一个新的对象,并且是一个无参的,那么这个时候编译器就不会自动生成了,所以这个时候这个无参的构造的函数只能用户自己定义,不然就直接报错了。❌❌❌
可以看到,如果我们将上面那段代码里面的无参构造方法删除后,代码就直接报红了。
🌕6,在构造方法的内部如果对成员属性进行赋值要善用this。
🚩注意:既然这里提到了this,那有一个面试的问题就是为什么说this代表的是当前对象的引用,而不是对象本身呢?对呀,这是为什么呢,我百思不得其解…
后来在我们的大学城B站上,看到了一位名叫大博哥的牛人的讲解,一下子我就开窍了,原因其实很简单,依旧是先有鸡还是先有蛋的问题。
原因解析:因为前面说了我们创建对象的过程是先分配内存空间,然后再调用构造方法创建对象,但是我们有可能在构造方法的内部就需要使用this,但是这个时候还在走构造方法,所以对象是还没有存在的,那你怎么会用得到对象呢,所以this在这里是不可能代表对象的,但是对象的内存空间是已经分配好了的,所以this代表的是这块内存空间,也即是对象的引用,利用对象的引用去 *** 作成员属性。
🚩this的扩展作用:
🔥1,this()可以调用自己的构造方法。
class Person{
private String name;
private int age;
public Person(){
this("xiaowang",20);//this调用自己的构造方法
System.out.println("Person<> init");
}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("Person init" );
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TestDemo220507 {
public static void main(String[] args) {
Person per1 = new Person();
System.out.println(per1);
}
}
程序运行截图:
可以看到,我们在构造方法 Person() 里面调用了构造方法 Person(String name,int age),但是要注意,这个只能用在构造方法里面,并且只能写在第一行,也只能调用一次。
🔥2,this.成员名 ,可以调用当前对象的属性。
🔥3,this.方法名 , 可以调用当前对象的方法。
🌕7,绝大多数情况下使用public来修饰,特殊场景下会被private修饰(后序讲单例模式时会遇到)。
🌈八,代码块 🌟8.1,代码块的概念及其分类
使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:
1,普通代码块(就是定义在方法里面,用{}括起来的部分,比较少见,没什么意义)
2,构造块
3,静态块
4,同步代码块(后续讲解多线程部分再谈)
🌟8.2,构造代码块(实例代码块)
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
class Student{
private String name;
private int age;
{//实例代码块
this.name = "xiaowang";
this.age = 10;
}
public Student(){
System.out.println("Student" );
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TestDemo220507 {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu);
}
}
程序运行截图:
可以看到,实例代码块定义在类中,并且可以用来对实例成员变量进行初始化。
🌟8.3,静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
class Student{
private static String name;
private static int age;
static{//静态代码块,初始化静态成员变量
name = "xiaowang";
age = 10;
}
public Student(){
System.out.println("Student" );
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TestDemo220507 {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu);
}
}
程序运行截图:
🌟8.4,实例代码块与静态代码块的初始化循序
class Person{
private String name;
private int age;
{
System.out.println("这是一个实例代码块!");
}
static{
System.out.println("这是一个静态代码块!");
}
public Person(){//构造方法
System.out.println("Person<> init");
}
}
public class TestDemo220507 {
public static void main(String[] args) {
Person per1 = new Person();
System.out.println("=========================");
Person per2 = new Person();
}
}
程序运行截图:
通过我们的运行结果可以看出,我们的静态的内容(方法,变量)都是类的属性,因此是在JVM加载类时开辟空间并执行初始化的,所以所有的静态的内容一定是最先初始化的,所以我们可以看到输出最先是输出的 “这是一个静态代码块”,当静态的内容初始化完了后,在进行创建对象的时候就会初始化我们的实例代码块,这个时候已经为对象开辟了空间,这也就是为什么在实例代码块里面可以用this对实例成员赋值,而静态的代码块里面不能用this对实例成员赋值了,因为静态代码块初始化的时候对象的空间都没开辟,实例成员又是属于对象的。并且通过运行截图,可以得知实例代码块的初始化也是在我们的构造方法之前的执行的。上面的代码里面我们new了两个对象,但是静态代码块只初始化了一次,说明无论构造多少个对象,对于静态的代码块而言,他只初始化一次。
总结,对于一个类而言,它里面的内容的执行顺序大概是:
🚩上面阐述了静态的内容都是最先初始化的,但是有多个静态的代码块,或者说静态的代码块与静态的成员之间又是怎样的顺序呢?其实对于这个就没有很多弯弯绕绕了,就是看谁写在前面,就先初始化谁。
class Person{
private String name;
private int age;
static{//静态代码块
count = 100;
System.out.println("这是一个静态代码块!");
}
public static int count = 0;//静态成员变量
}
public class TestDemo220507 {
public static void main(String[] args) {
System.out.println(Person.count);
}
}
程序运行截图:
可以看到,我们将静态的代码块写在前面,他就会先初始化静态代码块的内容,后面才初始化静态的成员变量,所以最终count的值是0,而不是100。
今天的分享就到这里了,如果大家觉得不错的话,还请帮忙点点赞咯,十分感谢呢!🥰🥰🥰
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)