java this( )什么时候用_JAVA-初步认识-第七章-this关键字什么时候用

一.

开发的时候,到底什么时候写静态?

首先要明确的是static是修饰符,它只能修饰一个东西,就是成员(成员分两种,变量和方法)。

static可以修饰两种成员,现在讨论的是,它什么时候可以修饰这两种成员的问题。

静态什么时候用?

推理分析:

1. 静态变量。

先要知道加static和不加static的区别在哪?也是问静态变量和成员变量的区别。→成员变量一词固定为不加static的变量了么?

不加static是在对象里边,加static是在方法区里面。

不加static,对象特有。加了static对象共有。

什么时候变量需要静态化。→首先是这样的,堆内存是存储对象的,如果有一个成员变量对于所有对象来说都是一样的(比如相同国籍的人),在class类的成员变量的描述中写成String country="China"。这样,堆内存中的对象每一个里面都有一个country="China",如果对象很多的话,那么country="China"就会变的很占内存。为了缓解内存占用的问题,提出了静态变量的解决方法。这也是变量静态化的起源。

静态修饰可以将country="China"抽离出堆内存,那么抽离出来的数据放置在内存中哪里?方法区里,静态数据。

我们说对象里面都会持有相同的属性,因为根据同一个类创建的,创建完以后都具备相同属性,都有相同值,因为它们都有默认初始化值。默认完以后,它还在具备相同的效果时,它不需要做改变,只要拿过来用的话,这个值就是静态值,如果对象需要做改变,或者说有一个对象的值是可以改变的,那就不能静态。这就是我们说的共有数据和特有数据的区别。对象都用同一个数据,这个数据就是共有数据。

描述事物的时候,我们要分析事物的属性,如果我们发现事物这个属性的值全都是一样的,而且一般不变化,这个属性就被定义为静态属性。判别是共有的还是特有的,再做是否是可以用static修饰。

2. 静态函数

函数是对外提供的,我提供给对方的函数到底是静态的呢?还是非静态的呢?因为函数可以直接被用户所调到,这个时候考虑,我们是加还是不加。

函数就是功能,函数是每个对象都具备的功能。那么这个功能是用对象来调用,还是用类来调用,区分就只有一个,就是这个函数里面有没有访问到对象中的特有数据。看着是,函数访问了对象中的非静态变量,那么它就是非静态函数。为什么?有什么用?

7641e0b14039a9d60d0f3152e83fb679.png

对2.静态函数的解析,第一句是按内存讲的,第二句是按源代码讲的。

对第一句从内存开始分析。对speak方法,先用静态试试,如果出错,再将static去掉。

定义了一个speak()方法,它的功能是说出年龄。static是修饰符,加或不加,都不会改变它的功能。

1663dab38ea10faf866a97d0e16bcadd.png

我们要从内存开始分析。如果在主函数中真的创建一个对象,并调用speak()方法。意味着堆里面有了一个对象Demo,对象里面有一个age变量(默认初始化为0),没有num,num变量是static修饰的,是共享数据,不在对象里,在方法区内静态数据。speak()方法要使用age变量,但是age是对象的特有数据,这个特有数据不是指age,而是age的数值0。new Demo.speak()就是在调用speak(),speak()方法在执行的时候,用到了age,只能是非静态的了。在描述类中,先有变量的描述,接着是方法的描述。变量根据是特有还是共享,来确定其是静态还是非静态。然后,方法再依据使用的变量是静态还是非静态,来确定自己是否要用static修饰。

如果在这里非要给speak()方法,加上static修饰符,那就意味着没对象这方法就能执行。但是没有对象,就没有age,而且age前面其实是this.age,那么this也不能写。因为static修饰的方法不需要访问对象,

0453ecf1e556cc40748f5fd0310bb992.png

对speak()方法中的输出再次进行一个修改,再判定方法是否用static修饰。

如果speak()方法的输出语句中,输出的是“哈哈”。对于“哈哈”而言,在描述类中是没有定义字符串类型的变量的。(我觉着方法既然没有访问对象,那就可以用static修饰)→答案:加或不加都一样,既能编译又能运行(这里面为什么会存在一个只用java工具运行的情况?),(不加static,加了之后生命周期变长。→生命周期一样,因为方法,方法中都是一样的,只有所属不一样,一个所属this,一个所属类名?)。

静态和非静态都可以用,把内存图一画,就明白了。

ae3d2d4fde4bb42b9d6d82fc55683491.png

不加static,看能不能用,将new.Demo().speak()进行了修改,改为了Demo d=new Demo(),d.speak(),虽然将一句拆成了两句,但本质是一样的。speak()方法没有访问特有数据,可是我们不加static(因为也没有使用静态变量,不是说没有使用特有变量,就必须加上static。应该这么说方法使用到了静态变量,就要加static修饰)。

3d29ac25db5fdef94d2354e05c1f5de5.png

我们从内存角度剖析这个程序,主函数中创建了一个对象,那么堆内存中就要开辟一个空间作为对象,同时分配地址编号,对象进行默认初始化(是不是每一个新建对象都有默认初始化,和构造函数初始化?)。先是栈中载入主函数,主函数中载入变量d,然后才有堆中对象的创建。在堆中对象初始化完毕后,将其地址赋值给d,从而d可以指向堆中的对象。主函数中的第二句是d.speak(),这意味对象调用了无参数的speak()方法,也就是说speak方法开始进栈。这时,speak方法中要指明是哪一个对象的调用,即用this来指代对象的地址编号,将对象的地址编号0x0045赋值给this(这个this是可以隐藏的么?是每一个方法都会存在的么?)。这样speak方法就指向了对象,接着speak方法运算完,输出“哈哈”,然后弹栈。从头到尾,新建的对象没有任何作用。

5eeacbf58e5998a27d495730d1194e9e.png

接着对程序进行一下修改,对对象进行一些确定的构造函数初始化,如下图所示。对象一初始化,就有年龄。对象一构造完,就从0变成了30。哪怕这里进行了特定的构造函数初始化,但是初始化都属于创建对象的过程,创建好对象后,该对象没有进行任何操作,程序就结束了。这里创建的对象除了浪费堆内存空间外,还要加载构造函数进栈出栈,没有其他的作用了(这里又想到关于堆内存中,无用数据的处理问题)。

这里其实就是想调用speak方法,输出“哈哈”,其实可以写成Demo.speak()。→匿名对象知识点不熟悉。

对象是封装特有数据的,没有访问特有数据,为什么要创建对象?

如果方法没有访问特有数据,对象创建是没有意义的,是在浪费空间。

因此本题是要加上static,是静态的,也就是通过类名来调用speak方法,只要能输出“哈哈”即可,而且也没有创建对象。设置成静态函数的目的就是为了,避开对象,通过类来调用方法。只要是非静态的方法,一调用,必然是通过对象来实现的。

只要方法访问的不是特有数据,就用static静态修饰方法。

b2eec982eeb0e2991e1f93eeafce1ecc.png

91a26a9d0075cd75dc1f485972e21f69.png

对象在默认初始化之后,可以选择各种各样的构造初始化,如果不选择或者没有构造函数的话,系统会有自动的构造函数进行初始化。我这里想说的是,为什么新建对象后面的括号里输入的数据就代表着特定的构造函数,同时也能给构造函数赋值?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java构造函数的重载指的是在同一个类中定义多个构造函数,它们的参数列表不同,可以有不同的参数类型、不同的参数个数或者参数顺序不同。这样做的目的是为了提供更灵活的对象创建方式,以满足不同的需求。 构造函数重载的语法格式与普通函数重载相同,只是函数名必须与类名相同。例如: ``` public class Person{ private String name; private int age; public Person(){ // 无参构造函数 } public Person(String name){ this.name = name; } public Person(int age){ this.age = age; } public Person(String name, int age){ this.name = name; this.age = age; } } ``` 在上面的代码中,Person类定义了4个构造函数,它们的参数列表分别是无参、字符串类型、整型和字符串类型加整型。通过构造函数重载,我们可以根据不同的参数来创建不同的Person对象。例如: ``` Person person1 = new Person(); // 使用无参构造函数创建对象 Person person2 = new Person("张三"); // 使用字符串类型参数构造函数创建对象 Person person3 = new Person(18); // 使用整型参数构造函数创建对象 Person person4 = new Person("李四", 20); // 使用字符串类型和整型参数构造函数创建对象 ``` 注意,如果我们没有定义任何构造函数,Java会默认提供一个无参构造函数。如果我们定义了任何一个构造函数,Java就不会再提供默认的无参构造函数了。因此,如果我们需要使用无参构造函数来创建对象,就需要显式地定义一个无参构造函数。 构造函数重载可以帮助我们提供多种创建对象的方式,使得代码更加灵活和可扩展。同时,构造函数重载也是面向对象编程中的一种重要概念,需要我们理解和掌握。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值