面向对象的进阶---static

1.static   静态变量

package com.itheima.a01staticdemo01;

public class Student {
    private String name;
    private int age;
    public  static String teacherName;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

   public void study() {
       System.out.println(name+"在学习");
   }
   public void show(){
       System.out.println(name+","+age+" ,"+teacherName);
   }
}
package com.itheima.a01staticdemo01;

public class StudentTest {
    public static void main(String[] args) {
        //static修饰的techername共享
        //类名调用变量
        Student .teacherName="小陈老师";
        Student s1 = new Student("张三",18);
        s1.study();
        s1.show();
        Student s2 = new Student("李四",26);
        s2.study();
        s2.show();
    }
}

      


静态变量是随着类的加载而加载的,优先于对象的

对象s1提供地址值访问静态区的变量,如图 s1访问静态区,就是通过地址0X0011这个地址线找到了静态区的变量teachername

2.静态方法和工具类

package com.itheima.a01staticdemo02;
public class ArrutilTest {
    public static void main(String[] args) {
      //测试工具类的二个方法是否正确
        int[]arr={1,2,3,4,5};
        String str = Arrutil.pirintArr(arr);
        System.out.println(str);
        double[]arr1={1.1,2.2,3.3,4.4,5.5};
        double avg = Arrutil.getAverage(arr1);
        System.out.println(avg);
    }
}
package com.itheima.a01staticdemo02;

public class Arrutil {
    //私有化构造方法
    //目的:为了不让外界创建他的对象
    private  Arrutil(){

    }
    //需要定义为静态的,方便调用
    public  static String pirintArr(int []arr){
        StringBuffer sb=new StringBuffer();
        sb.append("[");
        for(int i=0;i<arr.length;i++){
            if(i==arr.length-1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]+",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
    public static double getAverage(double[] arr){
        double avg=0;
        for(int i=0;i<arr.length;i++){
            avg+=arr[i];
        }
        return avg/=arr.length;
    }
}

package com.itheima.a01staticdemo03;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        //1.创建一个集合用来存储学生对象
        ArrayList<Student> list = new ArrayList<>();
        //2.创建3个学生对象
        Student s1=new Student("zhangsan",18,"男");
        Student s2=new Student("lisi",19,"男");
        Student s3=new Student("wangwu",20,"女");
        //将三个学生对象添加在集合里
       list.add(s1);
       list.add(s2);
       list.add(s3);
       //4.调用工具类的方法
        int ageMax = Studentutil.getAgeMax(list);
        System.out.println(ageMax);
    }
}

package com.itheima.a01staticdemo03;

import java.util.ArrayList;
import java.util.List;

public class Studentutil {
    private Studentutil() {

    }

    public static int getAgeMax(ArrayList<Student> list) {
        int max=list.get(0).getAge();
        for (int i = 1; i < list.size(); i++) {
           //list.get(i)集合里的每一个元素 ,每个元素是一个学生对象,我们还需getAge获取到年龄之后再进行比较
            int tmpAge = list.get(i).getAge();
            if (tmpAge > max) {
                max = tmpAge;
            }
        }
        return max;
    }

}
package com.itheima.a01staticdemo03;

public class Student {
    private String name;
    private int age;
    private String gender;

    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}

3.总结

this表示当前地方调用的地址值 
比如图里的s1和s2就是方法调用者,  所以说s1的地址和this的地址一样
我们平常写javabean类的时候是因为变量的名字一样没有加this关键字,严格的讲应该加this

比如说这里  this.show2() ,执行s1.show1()的时候 我们是调用者s1调用了show1的方法,然后show1的方法里面s1调用了show2()方法

静态区没有this关键字

静态区的方法不能调用成员的变量 也就是实例变量

因为静态区没有this关键字 调用show方法的时候没有对象调用方法

非静态区的变量通过对象能找到静态区的变量 teachername

一、static关键字是什么?

static是静态的意思,是一个修饰符,就像是一个形容词,是用来形容类,变量,方法的。在声明static关键字时,可以在前面加上static修饰,用static修饰的成员变量称做类变量(static变量、静态变量)

        二、加了static关键字有什么用?

被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问
static还有一个很关键的作用就是可以通过static来构建一个静态代码块,在这个静态代码块中,你可以将一些变量初始化,在程序加载的时候static代码块是优先加载的,因此可以说成是用来形成静态代码块以优化程序性能.

三、static静态变量和实例变量

说了一些static关键字的基本理念和它的作用,空谈不行,要将其应用到实例化代码中,接下来讲讲静态变量和实例变量的声明

1、两种变量的声明

  • 比方说我们下面定义一个System类🎄
class System{
	int name;		//姓名
	int num;		//编号
	static int onlineNumber;	//在线人数
}
  • 可以看出,这里的姓名和编号都是属于普通的实例成员变量,但是对于在线人数onlineNumber,前面却加了static关键字,表明其是一个静态变量

注意:只要成员变量可以用static关键字修饰,普通的局部变量不可以,是非法的

实例变量就是非静态区的成员变量

2、两种变量的区别

对于实例变量,改变其中一个对象的实例变量不会影响其他对象的实例变量,因为它们在堆内存中是一块块独立的区域,各自有各自的内存,是互不相干的;但是你通过任何对象去修改一个static修饰的成员变量,都可以将其修改,改变其中一个对象的类变量会影响其他对象的这个类变量,通俗一点来讲就是对象共享类变量

在Java中,当程序执行的时候,类的【字节码文件】会被加载到内存中,如果类没有创建对象,则类的成员变量不会被分配内存,但对于类变量,也就是静态变量,它有在堆中有一个专属的静态变量区,,当JVM虚拟机将字节码加载到内存时,就会为这个onlineNumber在线人数在堆区中分配出一段空间用于放置💡
当你去通过类定义对象的时候,这个时候才会在堆内存中为不同的对象分配不同的内存空间,上面我们说过,所有对象的类变量都是相同的一块内存空间,光这么说太抽象了,我们来看个

【堆栈内存原理分布图】

  • 然后在配合一个示例,大家可以先对照着我前面讲的把这个逻辑理一遍🔍
public class User {
    //static修饰的成员变量,内存中只有一份,可以被共享
    public static int onlineNumber = 16;
    //静态成员变量,直接用类名访问

    //实例成员变量 - 用对象访问
    private String name;
    private int age;

    public static void main(String[] args) {
        //直接用类名访问,不用对象
        //1.类名.静态成员变量
        System.out.println(User.onlineNumber);

        //2.对象名.实例成员变量
        User u = new User();
        //System.out.println(User.name); 不能用类名去访问实例成员变量
        u.name = "张三";
        u.age = 21;
        System.out.println(u.name);
        System.out.println(u.age);
        System.out.println("-----------");
        u.onlineNumber++;       //新来了一个人

        User u2 = new User();
        u2.name = "李四";
        u2.age = 22;
        System.out.println(u2.name);
        System.out.println(u2.age);
        System.out.println("-----------");
        u2.onlineNumber++;       //体现了共享的特点


        System.out.println(u.onlineNumber);
        System.out.println(User.onlineNumber);
        System.out.println(onlineNumber);
        //同一个类中静态成员变量的访问可以省略类型
    }
}

这个是运行结果

每个对象都指向堆区中的一块内存地址,每一块内存地址都是独立的,互不干扰,但是后面可以看出,两块不同的堆区内存均指向同一块静态变量区的地址,这就很好地印证了我上面说的那一点,所有对象的类变量都是相同的一块内存空间,也就是对象调用静态变量都能用.

因为对象调用的时候是在静态区调用的

  • 从运行结果可以看出,通过下面两条语句,看运行结果,都可以实现在线人数的递增,这就印证了对象共享类变量这句话📖
u.onlineNumber++;
u2.onlineNumber++;
  • 有一点要注意的是这句代码是不可行的,上面讲到过,当还没有通过类去构建对象的时候,是不会在堆内存中为其分配空间的,也就是说,这个时候堆内存中完全没有name这个变量,那你去直接用类名访问的话,是在访问哪个对象的姓名呢?
  • 有一点要注意的是这句代码是不可行的,上面讲到过,当还没有通过类去构建对象的时候,是不会在堆内存中为其分配空间的,也就是说,这个时候堆内存中完全没有name这个变量,那你去直接用类名访问的话,是在访问哪个对象的姓名呢?
//System.out.println(User.name); 不能用类名去访问实例成员变量
  • 好,我们讲本小块的最后一个知识点,就是如何去访问这个静态成员变量,一共是有下述三种方法,这三种方法就对应最后的这三句代码
    ①类名.静态成员变量(推荐)
    ②对象名.静态成员变量(不推荐)
    ③同一个类中,访问静态成员可以省略类名不写
  •  System.out.println(u.onlineNumber);
     System.out.println(User.onlineNumber);
     System.out.println(onlineNumber);
     //同一个类中静态成员变量的访问可以省略类型
    

四、static静态方法和实例方法

1、两种方法的声明

//静态方法 - 实现通用功能
public static int getMax(int x,int y){
	return x > y ? x : y;
}

//实例方法 - 直接访问对象的实例成员
public void speak(){
	name = "张三";
	System.out.println(name + "在说话");
}
  • 通过以上代码,相信大家对静态方法和实例方法有了一个基本的认识,在声明方法时候
  •  如果你想要实现一个通用功能,那就用静态方法;
  •  但如果你想要直接访问对象的实例成员,则用实例方法

注意: static关键字需要放在方法的类型之前,而不可以乱放置;而且不可以用static修饰构造方法

2、两种方法的区别

  • 上面在说到类加载时的字节码文件会被加载到内存中,而方法中存在一个入口地址,类的实例方法不会被分配入口地址,只有当该类创建了对象后,类中的实例方法才会被分配入口地址。而且当你创建了一个对象之后再继续创建对象时,不会再为实例方法分配入口地址,通俗地说就是,方法的入口地址所有对象共享
  • 在实例方法中你不仅可以操作实例变量,而且可以操作类变量,也就是static变量
  • 对于实例方法,它还可以调用类中其他的实例方法和类方法(不包括构造方法)
public static void main(String[] args) {
    //1.类名.静态成员方法
    System.out.println(Student.GetMax(10, 30));
    System.out.println(GetMax(50, 99));     //可不用类名

    //study();     需要对象名去访问
    //2.对象名.实例方法
    Student st = new Student();
    st.name = "孙悟空";
    st.study();

    //3.对象名.静态成员方法(语法可行,但是不推荐)
    System.out.println(st.GetMax(1,9));
}

  • 从上述代码我们可以看出静态成员方法和实例成员方法的调用格式,对于静态成员方法,它的格式有两种,我们也是推荐第一种,因为系统也是支持第一种调用方法,
  • ①类名.静态成员方法
    ②对象名.静态成员方法(语法可行,但是不推荐)
    对于这个,大家可以记住一句话

对于静态的东西,直接用类名调用即可,不会出错

  • 而对于这个实例成员方法,则只能用对象名去调用,因为其是属于对象的一部分,和实例成员变量一样,不可以用类名去调用,更不能直接调用,因为具体的对象其所对应的具体方法,内部的成员变量 也是相互对应的

五、static关键字注意事项

1、静态方法只能访问静态的成员,不可以’直接’访问实例成员
2、实例方法可以访问静态的成员,也可以访问实例成员
3、静态方法中是不可以出现this关键字的

  • 最后一点,就是对于静态方法中不可以出现this关键字,因为this代表的是当前对象,静态方法中是可以不用声明实例对象的,但是this可以出现在实例方法中,就如上一个注意事项中的最后一句代码,this代表正好是这个对象所对应的地址,就可以访问其所对应的成员变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/720484.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端传进来的单选值是0,到了后端加了个逗号

如上图所示&#xff0c;标记的var的值org和id的值orgOrNot不能一样&#xff0c;如果一样&#xff0c;通过id获取&#xff08;#(“#orgOrNot”).find(“option:selected”).val()&#xff09;时候就会出现这种情况 改成如下情况&#xff0c;区别开id

C++ 61 之 函数模版

#include <iostream> #include <string> using namespace std;void swapInt(int &a,int &b){int temp a;a b;b temp; }void swapDou(double& a, double& b){double temp a;a b;b temp; }// T代表通用数据类型&#xff0c;紧接着后面的代码&a…

做户用光伏代理需要多少钱?

随着全球对可再生能源和清洁能源的关注度日益提高&#xff0c;光伏技术作为其中的佼佼者&#xff0c;已经成为许多投资者和创业者关注的焦点。户用光伏系统作为其中的一个重要分支&#xff0c;其市场潜力巨大&#xff0c;吸引了越来越多的投资者和创业者进入这一领域。那么&…

Linux实现: 客户端(cli01)通过TCP(或UDP)连接到聊天服务器(serv)进行聊天?(伪代码版本)

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

使用 C# 学习面向对象编程:第 7 部分

多态性 我们在程序中使用多态的频率是多少&#xff1f;多态是面向对象编程语言的第三大支柱&#xff0c;我们几乎每天都在使用它&#xff0c;却不去想它。 这是一个非常简单的图表&#xff0c;它将解释多态性本身。 简单来说&#xff0c;我们可以说&#xff0c;只要我们重载类…

音乐管理系统 SpringBoot + vue

文章目录 1、简要介绍2、数据库设计3、解决的问题1、图片和音频的上传和存储2、分页功能 4、数据返回 也算是进行了半个学期&#xff0c;跟着老师讲的进行 后端使用SpringBoot 前端 vue layui jdk 18 项目地址&#xff1a;gitee 1、简要介绍 只有管理端&#xff0c;但是对用…

超多细节—app图标拖动排序实现详解

前言&#xff1a; 最近做了个活动需求大致类似于一个拼图游戏&#xff0c;非常接近于咱们日常app拖动排序的场景。所以想着好好梳理一下&#xff0c;改造改造干脆在此基础上来写一篇实现app拖动排序的文章&#xff0c;跟大家分享下这个大家每天都要接触的场景&#xff0c;到底…

Golang并发控制的三种方案

Channel Channel是Go在语言层面提供的一种协程间的通信方式&#xff0c;我们可以通过在协程中向管道写入数据和在待等待的协程中读取对应协程的次数来实现并发控制。 func main() {intChan : make(chan int, 5)waitCount : 5for i : 0; i < waitCount; i {go func() {intC…

ISCC2024 WriteUp

msic Funzip Funzip writeup解题思路 1.打开题目发现是一个base64 2.看了一遍后发现他不是很全于是写一个脚本进行补全 wf open("5.txt", "w") with open("1 (2).txt", "r") as f: data f.read() data data.splitlines() for l…

【AI+多智能体框架】个人整理的几款AI多智能体框架

昨天无意间了解到 alipay开源 的多智能体框架agentUniverse &#xff0c;这里聊一下。现在这个信息社会&#xff0c;讲究多角色协同工作。人工智能时代&#xff0c;多智能体协同工作也是大势所趋&#xff0c;虽然现在框架或多或少还存在瑕疵。 但所有新技术都是在发展中逐步迭代…

vue引入aos.js实现滚动动画

aos.js官方网站&#xff1a;http://michalsnik.github.io/aos/ aos.js介绍 AOS (Animate on Scroll) 是一个轻量级的JavaScript库&#xff0c;用于实现当页面元素随着用户滚动进入可视区域时触发动画效果。它不需要依赖 jQuery&#xff0c;可以很容易地与各种Web开发框架&#…

掌握rpc、grpc并探究内在本质

文章目录 rpc是什么&#xff1f;又如何实现服务通信&#xff1f;理解rpcRPC的通信过程通信协议的选择小结RPC VS Restful net_rpc实践案例net/rpc包介绍创建服务端创建client 看看net_rpc的通信调度实现的内部原理明确目标基于自己实现的角度分析我会怎么做代码分析 grpc介绍与…

QT修改界面图标及exe程序图标

目录 步骤1. 添加图标文件2. 添加保存图标变量3. 窗口启动初始化图标文件4. 构建后即可完成图标的更改 步骤 1. 添加图标文件 如下&#xff0c;添加一个名为 favicon.ico 的文件到.pro 工程文件所在的目录中。 2. 添加保存图标变量 RC_ICONS是一个变量&#xff0c;它被用于存储…

MaxKB-无需代码,30分钟创建基于大语言模型的本地知识库问答系统

简介 MaxKB 是一个基于大语言模型 (LLM) 的智能知识库问答系统。它能够帮助企业高效地管理知识&#xff0c;并提供智能问答功能。想象一下&#xff0c;你有一个虚拟助手&#xff0c;可以回答各种关于公司内部知识的问题&#xff0c;无论是政策、流程&#xff0c;还是技术文档&a…

老杨说运维 | 如何结合现状进行运维路径建设(文末附演讲视频)

青城山脚下的滔滔江水奔涌而过&#xff0c;承载着擎创一往无前的势头&#xff0c;共同去向未来。2024年6月&#xff0c;双态IT成都用户大会擎创科技“数智化可观测赋能双态运维”专场迎来了完满的收尾。 本期回顾来自擎创科技CTO葛晓波的现场演讲&#xff1a;数智化转型的核心目…

Ps:脚本与动作

有三种脚本语言可用于编写 Photoshop 脚本&#xff1a;AppleScript&#xff08;macOS&#xff09;、JavaScript 和 VBScript&#xff08;Windows&#xff09;。 Photoshop 脚本文件默认文件夹 Win&#xff1a;C:\Program Files\Adobe\Adobe Photoshop 2024\Presets\Scripts Mac…

lombok不起作用排查

1.idea中lombok插件已安装并启用 2.idea中annotation processors已勾选 3.项目中gradle或maven已引入lombok依赖 但提示还是找不到get,set方法。 还需要启用annotationProcessor 重点是annotationProcessor的配置&#xff0c;没有配置这个才是问题出现的关键&#xff01;&…

【机器学习300问】124、什么是LSTM?LSTM的基本结构是怎样的?

长短期记忆网络&#xff08;LSTM&#xff09;是一种解决隐变量模型长期信息保存和短期输入缺失问题的方法&#xff0c;有趣的是&#xff0c;长短期记忆网络的设计比门控循环单元稍微复杂一些&#xff0c; 却比门控循环单元早诞生了近20年。 一、什么是LSTM&#xff1f; LSMT全…

Character Animator 2024 mac/win版:赋予角色生命,动画更传神

Character Animator 2024是一款强大的角色动画制作软件&#xff0c;以其创新的功能和卓越的性能&#xff0c;为动画师、游戏开发者以及设计师们带来了全新的创作体验。 Character Animator 2024 mac/win版获取 这款软件采用了先进的骨骼绑定技术&#xff0c;使得角色动画的制作…

图解ZGC

ZGC&#xff08;Z Garbage Collector&#xff09; 是一款性能比 G1 更加优秀的垃圾收集器。ZGC 第一次出现是在 JDK 11 中以实验性的特性引入&#xff0c;这也是 JDK 11 中最大的亮点。在 JDK 15 中 ZGC 不再是实验功能&#xff0c;可以正式投入生产使用了&#xff0c;使用 –X…