【Java】面向对象之类和对象,浅谈static修饰符和this关键字,初识JVM

目录

1:从static层面区分类的结构:

1.1:static系列:

补充:

本人一些浅显的理解:

补充this关键字 作用

this关键字作用(1)

this的身影

this关键字作用(2)

2:从类的内容层面了解类

我们知道类包括五种

3:对象

3.1:面向对象三个层次:

3.2:对象的声明,其物理层面的操作及其存储:

3.2:你对象没了!浅谈对象的消亡:

——————————补充内容————————————

4:初识JVM

4.1:JVM是什么

4.2:JVM的内容:

4.2.1:方法区:method

4.2.2:堆:

4.2.3:栈:

4.2.4:程序计数器(ProgramCounter)寄存器:

4.2.5:运行时常量池:

4.2.6:本地方法栈:

5:变量

6:方法

静态方法VS普通方法

6.1:静态方法,

6.2:普通方法,

6.3:构造方法

7:两小儿辩static

7.1:效率:

7.2:优势与弊端:

8:小结


1:从static层面区分类的结构:

1.1:static系列:

/*
static系列:

类变量(也叫静态变量)

类方法(也叫静态方法)

静态代码块(静态构造代码块)    
*/

static系列的内容都是某种意义上可以理解成和对象无关的,即跟着类走的只跟类有关。

(1)在静态方法中不可以使用this关键字, 无法从 static 上下文引用this关键字

(2)在静态方法中不可以直接调用非静态方法。 无法从 static 上下文引用非 static 方法 'test()'譬如在前期学习时我们初识方法,我们规定代码书写过程中一律给自己写的方法都加上两个修饰符 public和 staic ,其中static修饰符就是为了方便我们在main 函数做为入口,在静态方法main中直接调用我们写的静态方法!

public class test1_20211128 {
    public void test(){
        System.out.println("for test.");
    }

    public static void main(String[] args) {
        test();
    }
    
}

 无法从 static 上下文引用非 static 方法 'test()'


补充:一些浅显的理解:

为什么有些方法用static修饰,可以直接通过类名.静态方法来进行调用?而有些必须将类实例化之后才能通过对象名进行调用?

世界上没有两片完全相同的叶子,类是模子,但是刻画出来的对象也有各自的特征。

不妨想一想:力扣刷题时 我们经常用到的 非静态方法:

toCharArray()    这个方法需要特定对象才可调用把他从一个字符串返回成为一个字符数组。

还有求字符串的长度的length()方法,这些都需要用到字符串的特征。

而valueOf()方法则是静态的,不需要对象的具体特征,不需要依靠对象,直接把一个字符数组 返回为 一个字符串对象。

虽然静态方法也可以使用“对象.静态方法”的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态方法和非静态方法,也违背了将通用抽象方法写作static,不需要具体对象特征就能调用的初衷!

虽然静态变量也可以使用“对象.静态成员”的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态成员和非静态成员。


this关键字的作用

this关键字作用(1)用来表明当前正在构造的对象

用来表明当前正在构造的对象。用在对象内来加以区分,防止传进来的形参 和 类内方法的变量重名,方法之内局部变量优先,形参先于实参,但那时形参自己给自己赋值,传进来的值无意义,不能起到实际作用,当setter改变不了要改变的对象内的值,就要使用this加以区别。

package Person;

public class PersonTest {
    private String name = "srs";
    private int date = 312;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        name = name;
    }

    public int getDate() {
        return date;
    }

    public void setDate(int date) {
        date = date;
    }

    public static void main(String[] args) {
        PersonTest personTest = new PersonTest();
        System.out.println(personTest.date);
        System.out.println(personTest.name);
    }

}

此处输出结果就是初始值312 和 srs 我们调用访问器方法对其进行更改:

    public static void main(String[] args) {
        PersonTest personTest = new PersonTest();
        System.out.println(personTest.date);
        System.out.println(personTest.name);
        personTest.setDate(666);
        personTest.setName("nbnb");
        System.out.println(personTest.date);
        System.out.println(personTest.name);
    }

结果如上图所示,传进去的实参并没有起到实际的作用。


 我们加上this之后再进行测试:

加上this之后输出结果如下,显然通过访问器可以对其进行修改了!


this的身影

初识类与对象,对这些抽象的概念我们都很疑惑,那么在哪儿能找到this呢?

万事不决Debug!

我们在debug中可以找到this的身影,别说,this这小东西还挺别致,挺能藏,我之前学习还没发现debug中能找到,多亏了老陈,对暗号:老陈YYDS!


this关键字作用(2)

 我们可以使用this()调用构造方法

其中括号内可以与其他构造方法的参数列来调用其他构造方法,但是传进去的必须是实参:

如此处通过this(20211128);可以调用,而不能 this(int date);

package com.zdx.csdn.blog.test;

public class test1_20211128 {
    public static void main(String[] args) {
        new TestConstructor();
    }
}
class TestConstructor{
    int date;
    TestConstructor(int date){
        System.out.println("参数列表不为空的构造方法"+date);
    }
    TestConstructor(){
        this(20211128);
        System.out.println("空构造方法");
    };

}

package com.zdx.csdn.blog.test;

public class test1_20211128 {
    public static void main(String[] args) {
        new TestConstructor(20211128);
    }
}
class TestConstructor{
    int date;
    TestConstructor(int date){
        this();
        System.out.println("参数列表不为空的构造方法"+date);
    }
    TestConstructor(){

        System.out.println("空构造方法");
    };

}

通过对比:我们发现this的第二个作用,引用其他的构造方法的特点

一言以蔽之:在构造方法中使用this可以调用不同于当前构造方法的参数列的其他任意方法(但是受限于this语句必须写在构造方法第一行,只能调用一次;

不能调用参数列表相同的,是因为会形成递归。


2:从类的内容层面了解类

我们知道类包括五种

属性

方法

内部类

代码块(官名构造代码块!)

构造方法(严格意义上来说也可叫构造器!)

万物皆对象:

在逻辑层 >>>我们面向存在于开发人员脑海中的世界 >>对现实中的一类有形或无形的概念的特征抽取,

                        特征表现为属性,对其行为的抽取,表现为方法。

                        换言之,属性即是数据,方法即是针对数据的操作。

内部类我们暂时还不需要了解那么深;

随着后续的学习,当深入到继承时,还有父子类优先关系需要比较

类加载的优先级规则:

存在继承关系的不同类中,同一部分父类优先子类

同一父(子)类中static系列 优先于 不含 static 的一系列

同类型内(同是static,同非static)即:

1:默认值最先(即赋值为类0:数字赋0,布尔赋false,字符串赋""这种)最先

2:定义时初始化和代码块同等级,在代码中谁的位置在前,谁先执行

3:然后是构造器(构造函数)

package com.zdx.csdn.blog.test;

public class TestStaticVar {
    static int staticint = si();

    int one = un_si();

    public static int si(){
        System.out.println("静态变量被初始化");
        return 1;
    }

    public  int un_si(){
        System.out.println("成员变量one被初始化");
        return 2;
    }

    public static void main(String[] args) {
        new TestStaticVar();
        new TestStaticVar();
    }


}

静态对象(变量)优先于非静态变量(对象)初始化,其中,静态变量(对象只初始化一次)

非静态对象(变量)可能会初始化多次。


3:对象

3.1:面向对象三个层次:

1)概念层(现实生活中) 万物皆对象 风,过程(学习过程,入学时间,学习内容,操作系统中的进程)也是对象

2)逻辑层 >>>存在于开发人员脑海中的世界 >>对现实中的一类有形或无形的概念的特征抽取,

                        特征表现为属性,对其行为的抽取,表现为方法。

                        换言之,属性即是数据,方法即是针对数据的操作。

3)物理层 >> 对象在堆区,对象在堆上是怎么存的?

3.2:对象的声明,其物理层面的操作及其存储:

Person person = new Person();

对象的引用变量:在栈上 即等号左边的stu存储在栈上

Java中每次 new 的 出现即在内存(heap堆区域)要内存,由JVM分配空间。

此处就要提到JAVA的安全机制做的格外不错

等号右边的对象存储在堆上,我们根本拿不到地址

等号左边的存储在栈上,我们能拿到如下图的地址,但是经过哈希处理的! 

把这段内存区域,全部用0(或者null,或者false这种类似0的不同类型的初始值)去进行初始化,大略估计内存后对其进行分配。//这也就解释了为什么类内的成员变量需要初始化。

但是我们在堆上申请的内存是给对象用的!

//静态变量属于是初始化就焊死在JVM的方法区了。

本处所说的主要是指 Java 中 每次 有 new 出现 必有对象生成。

static变量 和 static方法 加上static 就和 对象无关了。static属于是跟着类走的,和类是一家人,类的预加载和 对象的初始化时两个阶段!


3.2:浅谈对象的消亡:

上文讲述了对象的诞生与操作。,对象的消亡指的是:

没有任何的引用指向它,他就死亡了,被称为垃圾

JVM中很重要的机制叫做垃圾回收,也就是JVM管杀管埋

Java舍弃了指针、舍弃了内存管理。说白了Java就是不信任所有的程序员都一定能够理性、安全和高效率的去处理这类复杂问题,

所以就在语言设计上用弱化复杂度(或者说灵活性、丰富度)去换取安全性罢了 。

每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由java虚拟机(JVM)自带的垃圾回收机制处理。不能再进行使用。

在学习垃圾回收机制之前,首先需要了解何种对象会被Java虚拟机视为垃圾:

  • 🔲对象引用超过其作用范围,这个对象将被视为垃圾;
  • 🔲将对象赋值为null


——————————补充内容————————————

4:初识JVM

4.1:JVM是什么

JVM是Java Virtual Machine的缩写。它是一种基于计算设备的规范,是一台虚拟机,即虚构的计算机。

JVM屏蔽了具体操作系统平台的信息(显然,就像是我们在电脑上开了个虚拟机一样),当然,JVM执行字节码时实际上还是要解释成具体操作平台的机器指令的。

通过JVM,Java实现了平台无关性,Java语言在不同平台运行时不需要重新编译,只需要在该平台上部署JVM就可以了。因而能实现一次编译多处运行。(就像是你的虚拟机也可以在任何安了VMWare的系统上运行)


4.2:JVM的内容:

JVM主要包括:程序计数器(Program Counter),Java堆(Heap),Java虚拟机栈(Stack),本地方法栈(Native Stack),方法区(Method Area)

4.2.1:方法区:method

又叫静态区,存放所有的

①类(class),

②静态变量(static变量),

③静态方法,

④常量

⑤成员方法(就是普通方法,由访问修饰符,返回值类型,类名和方法体组成)。

4.2.2:堆:

jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 。

4.2.3:栈:

Java栈的区域很小,只有1M,特点是存取速度很快,所以在stack中存放的都是快速执行的任务,每个方法执行时都会创建一个栈帧(Stack Frame),描述的是java方法执行的内存模型,用于存储局部变量,操作数栈,方法出口,基本数据类型的数据,和对象的引用(reference)等。每个方法的调用都对应的出栈和入栈。

4.2.4:程序计数器(ProgramCounter)寄存器:

PC寄存器( PC register ):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有当前正在执行的JVM指令的地址。

4.2.5:运行时常量池:

是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

4.2.6:本地方法栈:

本地方法栈与Java虚拟机栈发挥的作用非常相似,它们之间的区别在于虚拟机栈为虚拟机执行java方法(也就是字节码文件)服务,而本地方法栈则为使用到Native方法服务。


5:变量

目前学习见到的变量:

Java栈的区域很小,只有1M,特点是存取速度很快,所以在stack中存放的都是快速执行的任务,每个方法执行时都会创建一个栈帧(Stack Frame),描述的是java方法执行的内存模型,用于存储局部变量,操作数栈,方法出口,基本数据类型的数据,和对象的引用(reference)等。每个方法的调用都对应的出栈和入栈。


6:方法

静态方法VS普通方法

6.1:静态方法,

类方法 不能访问对象,因为他是预先加载的,static方法预先加载与成员变量一样,属于类的本身,在类加载的时候被装载到内存,不自动进行摧毁,会一直存储在内存中方法区,直到JVM关闭。

6.2:普通方法,

实例方法,成员方法,非静态方法 不加 static 实例化后才会分配内存,分配内存也在方法区。必须通过类的实例来引用。不会常驻内存,当实例对象(在Java中每次有new出现,必然在堆Heap上声明一块内存用来存储对象)被JVM回收(通常对象被JVM回收是因为他没有了引用变量指向它)之后,也跟着消失。

6.3:构造方法


7:两小儿辩static

首尾呼应,我们再看一下开始时看到的static修饰符!

7.1:效率:

静态方法的使用效率比非静态方法效率高。

7.2:优势与弊端:

静态方法是共享代码段,静态变量是共享数据段。既然是”共享”就有并发的问题。

非静态方法:必须经过实例化之后用对象.方法调用,针对于一个特定的对象:所以不会存在线程安全的问题。

但是静态方法和 静态属性 是按照修饰符,如public 被 可访问权限内共享的,如果多个线程进行操作,其中一个对static进行了更改,那么就是危险的。

静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。

例如:

不需要生成对象的 经常频繁使用的 工具类里的(如SqlHelper)

此外 不需要生成对象根据对象的专有特征(属性,成员变量)来调用的方法

如 力扣刷题常用的String 类里的length()和toCharArray()等方法上文已经讲过,此处不再展开。

在一些系统中较常使用,不需对象的特征,无奇技淫巧的方法都定义为静态方法可以提高系统性能。

但其本身不可升级,重写,这要看一个软件产品的目的是什么。

有时也为了方便快捷,通过类名直接调用而不用实例化,但这样程序编译运行时就占用了系统资源。且所以静态内容都需要预先加载。

各有千秋,诸君酌情使用。

8:小结

由于水平有限,能力欠佳,本文中难免存在不妥之处。还望读者不吝赐教,敬请斧正,初学Java,我们一起学习,共同进步!

面向对象面向君,不负代码不负卿。

看到这里,相信你已经对面向对象有了最基本的了解。

明来路,知去处。

一个对象的一生从同一个模子的类初始化创建独一无二的对象始,到对象操作,直至最后的消亡。

过眼涛涛云共雾,算人间知己吾和汝。

能否动动年薪百万的小手一键三连支持一下呢!你的支持就是我创作输出整理的最大动力!

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

傻根根呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值