Java面向对象编程-基础篇

1.对象在内存中的存在形式

假设代码如下:

Cat c = new Cat()
c.name = "小白";
c.age = 12;

在这里插入图片描述

  • 由于name属性为字符串类型,所以存放在方法区的常量池中
  • 在执行Cat c = new Cat()时会在方法区中加载类信息
  • c只是对象的引用,真正的对象是由new cat()创建的对象空间(在堆以及方法区中)

2.类和对象的内存分配机制

假设代码如下:

Cat c = new Cat()
c.name = "小白";
c.age = 12;
Cat d = c;

在这里插入图片描述

  • dc都是指向同一块内存地址,如果修改d.age=20c.age的值也会改变
  • 如果执行再d=nulld就不会再指向地址0x0011的内存空间,而是变为空指针(执行b.age会报错),c还是指向原来的地址空间
2.1.java内存的结构分析
  • 栈:一般存放基本数据类型(局部变量)
  • 堆:存放对象(数组等)
  • 方法区:常量池(字符串等)、类加载信息
2.2.java创建对象的流程分析

① 先加载Cat类信息(属性和方法信息只会加载一次)

② 在堆中分配空间,进行默认初始化

③ 把地址赋值给cc就指向对象

④ 进行指定初始化,比如c.age=15

tips:

  • 当对象指向null时,调用对象的方法会报错,所以判断时最好写为下面形式:
// 如果a指向null,不会报错
if("abc".equals(a)){
	return 0;
}
// 如果a指向null,会报错
if(a.equals("abc")){
	return 0;
}

3.方法的调用机制分析

假设代码如下:

Cat c = new Cat();
c.getSum(10,20);
/** --------- getSum-----------
void getSum(int a, int b) {
    System.out.println(a + b);
}
*/

在这里插入图片描述

  • 当程序执行到getSum方法时,会开辟一个独立的空间(栈空间)
  • getSum执行完毕后栈空间会自动销毁,main方法执行完毕时main栈也会自动销毁

4.方法的传参机制

4.1 基本数据类型

假设代码如下:

A o = new A();
int a = 10;
int b = 20;
o.swap(a, b);
System.out.println("main方法中a=" + a + "\tb=" + b);	// main方法中a=10	b=20
/**---------swap--------
public void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}
*/

在这里插入图片描述

  • main栈和swap栈是两个独立的空间,所以两个栈的a和b尽管名字一样,但是也是独立的
  • 基本数据类型传递是值拷贝,形参的改变不会影响实参
4.2 引用数据类型

假设代码如下:

A o = new A();
int[] a =  {1,2,3};
o.test(a);
System.out.println("main方法中的a[0]=" + a[0]);	// main方法中的a[0]=100
/**---------test--------
public void test(int[] a) {
    a[0] = 100;
}
*/

在这里插入图片描述

  • main栈和test栈是两个独立的空间,所以两个栈的a尽管名字一样,但是也是独立的。虽然是独立的,但是指向的是同一个地址
  • 引用类型传递是地址传递,形参的改变会影响实参

tips:

  • 如果将test函数中改为a=null,最后输出a[0]还是1。因为执行a=null后test栈中的a就不再指向地址0x0022,即不会影响该地址中的值

5.方法重载注意事项

假设代码如下:

public void test(int[] a) {
    System.out.println(a[0]);
}
public int test(int[] a) {
    return 1;
}

上述两个方法不属于方法重载,会报错

  • 方法名相同
  • 形参列表必须不同(类型或个数或顺序至少一个不同,参数名无要求)
  • 对于返回类型无要求,所以上述代码会报错(如果执行a.test(...),即使函数有返回值也可以不接收,和函数没有返回值一样,系统不知道要执行哪个函数)

6.可变参数

假设代码如下:

public void test(int[]... nums) {
    System.out.println(nums.length);
}
  • java允许将同一个类中多个同名同功能但参数个数不同的方法封装为一个方法,可以通过可变参数实现
  • int[]…:表示接收的是可变参数,类型为int[],可以接收0个或多个
  • 使用可变参数时,可以当作数组进行使用,即nums为数组

tips:

  • 可变参数可以和普通类型放在一起,但是可变参数一定要放在最后
  • 一个形参列表只能出现一个可变参数

7.作用域

  • 全局变量:就是属性,作用域为整个类体。可以不赋值直接使用,因为有默认值
  • 局部变量:除了属性外的其他变量,作用域在定义它的代码块中。必须赋值,因为没有默认值
  • 全部和局部变量可以重名,访问时遵循就近原则
  • 全局变量生命周期长,随着对象创建而创建;局部变量生命周期短,随着代码块执行而创建
  • 全局变量可以加修饰符,局部变量不行

8.对象创建流程分析

假设代码如下:

public static void main(String[] args) {
    Person p = new Person("psw", 20);
}
/**---------Person类--------
class Person {
    int age = 10;
    String name = "psj";

    Person(String n, int a){
        name = n;
        age = a;
    }
}
*/

在这里插入图片描述

① 在方法区中加载Person类信息(Person.class),且只会加载一次

② 在堆中分配空间

完成对象初始化

  • 先完成默认初始化 age=0,name=null
  • 再完成显示初始化age=10,name=”psj“
  • 最后才完成构造器初始化age=20,name=”psw“

④ 把对象在堆中的地址返回给对象引用p


9.this的使用

假设代码如下:

public static void main(String[] args) {
    Person p = new Person("psw", 20);
    p.info();
}
/**---------Person类--------
class Person {
    int age;
    String name;

    Person(String name, int age) {
        name = name;
        age = age;
    }
    void info(){
        System.out.println(name + '\t' + age);
    }
}
*/
  • 此时执行p.info()后打印出null 0,即打印的是Person类属性的默认值。这是因为构造器的name和age是局部变量,不是属性(符合就近原则)
  • 修改为this.name=namethis.age=age后,this.name指的就当前对象的属性name

在这里插入图片描述

  • 堆中对象空间存在this指向当前对象的地址
  • 哪个对象调用(比如创建Person p1、p2等),this就代表哪个对象

tips:

  • this可以访问本类的属性、方法、构造器。在访问构造器语法为:this(参数列表),但是只能在本类中一个构造器中调用另一个构造器,不能在普通方法中去调用构造器,并且调用语句一定是第一条语句
  • this不能在类定义外部使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 7-6 jmu-java-03面向对象基础-02-构造方法与初始化块是一门Java编程课程,主要讲解面向对象编程中的构造方法和初始化块的概念、使用方法和注意事项。通过学习这门课程,可以更好地理解Java中的面向对象编程思想,掌握构造方法和初始化块的使用技巧,提高Java编程能力。 ### 回答2: 面向对象编程中,我们经常需要创建多个对象,每个对象都有各自独有的属性和方法。在创建对象的过程中,我们需要对对象进行初始化,即设置对象的属性和调用对象的方法。在Java编程语言中,构造方法和初始化块是两种非常重要的初始化对象的方式。 构造方法是一种特殊的方法,可以在创建对象时调用,用于初始化对象的属性和执行一些必要的操作。构造方法和类名必须相同,并且没有返回值。在构造方法中,我们可以设置对象属性的默认值,传入参数初始化对象属性的值,或执行一些其他的操作。如果没有定义构造方法,Java会自动添加一个无参构造方法。 初始化块是在类加载时执行的一段代码块,可以用于初始化静态属性或实例属性。初始化块可以有多个,按照定义的顺序执行,并且可以包含任意合法的Java语句。静态初始化块只会在类加载时执行一次,而实例初始化块则在对象创建时每次都会执行一次。 构造方法和初始化块都是在对象创建时进行初始化的过程,但是两者还是存在一些区别。首先,构造方法只能用于初始化实例属性,而初始化块既可以初始化静态属性也可以初始化实例属性。其次,构造方法可以接受参数,根据传入的参数初始化实例属性的值,而初始化块不能接受参数。 在实际编程中,我们需要根据实际需求选择合适的初始化方式。如果只需要初始化实例属性,可以使用构造方法来进行初始化;如果还需要初始化静态属性,可以使用静态初始化块;如果需要在创建对象时执行一些复杂的操作,可以使用初始化块。通过灵活使用构造方法和初始化块,我们可以更好地进行对象初始化,提高程序的性能和可维护性。 ### 回答3: 在Java类中,构造方法和初始化块都是用来初始化对象的。它们可以执行变量初始化、方法调用和其他操作。本文章将主要介绍构造方法和初始化块的区别和作用。 构造方法 构造方法是一种特殊的方法,其作用是创建对象时初始化对象的状态。每个类都至少拥有一个构造方法,并且构造方法的名称必须与类名相同。构造方法没有返回类型,并且不能被声明为final、static或abstract。在Java中,构造方法有以下特点: 1. 构造方法没有返回类型 2. 构造方法的名称必须与类名完全相同 3. 构造方法可以重载,即同一个类中可以定义多个不同的构造方法,只需要使用不同的参数列表即可 4. 如果没有定义构造方法,则Java编译器会为类自动添加一个默认的构造方法 构造方法的作用主要有两个: 1. 初始化实例变量:构造方法可以在对象创建时给实例变量赋初值,为了方便,在Java中,经常将对象属性的初始化操作放到构造方法里实现。 2. 对象创建时执行的操作:构造方法可以执行一些对象创建时必要的操作,比如打开文件、建立网络连接等操作。 初始化块 初始化块是一个没有任何修饰符的代码块,它可以出现在类中的任何地方。初始化块在对象创建时执行,它可以用来对静态属性或实例属性进行初始化。初始化块的主要作用是为类实例的属性提供默认值。 在Java中,初始化块有以下特点: 1. 初始化块没有任何修饰符。 2. 初始化块不像方法一样需要被调用,它会在类被加载时自动执行。 3. 初始化块可以定义多个,且执行顺序按照定义的顺序执行。 4. 初始化块和构造方法的区别是:构造方法是为了初始化对象时的属性值,而初始化块是为了初始化对象创建时必要的操作。 总结 构造方法和初始化块都是用来初始化对象,在Java中,构造方法主要用来在对象创建时初始化实例变量或执行一些必要的操作,初始化块主要用来为类实例的属性提供默认值。它们的主要区别在于: 1. 构造方法是构造对象的,初始化块是初始化对象的。 2. 构造方法是有参数的,而初始化块是没有参数的。 3. 构造方法必须显式地被调用,而初始化块则是在类被加载时自动地执行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值