day13_static丶代码块丶final

static

static 概述 :static 是 java 语言中的关键字,表示“静态的”,它可以用来修饰变量、方法、代码块等, 修饰的变量叫做静态变量,修饰的方法叫做静态方法,修饰的代码块叫做静态代码块。在 java 语言中凡是用 static 修饰的都是类相关的,不需要创建对象,直接通过“类名”即可访问,即 使使用“引用”去访问,在运行的时候也和堆内存当中的对象无关。

使用范围:
  • Java类中,可用static修饰属性、方法代码块、内部类
  • 被修饰后的成员具备以下特点:
  • 随着类的加载而加载
  • 优先于对象存在
  • 修饰的成员,被所有对象所共享
  • 访问权限允许时,可不创建对象,直接被类调用
静态属性、静态方法的设计思想
  • 静态属性作为该类各个对象之间共享的变量。在设计类时,分析哪 些属性不因对象的不同而改变,将这些属性设置为静态属性。相应 的方法设置为静态方法。
  • 如果方法与调用者无关,则这样的方法通常被声明为静态方法,由 不需要创建对象就可以调用静态方法,从而简化了方法的调用。

静态变量

  • java 中的变量包括:局部变量和成员变量,在方法体中声明的变量为局部变量,有效范围 很小,只能在方法体中访问,方法结束之后局部变量内存就释放了,在内存方面局部变量存储 在栈当中。在类体中定义的变量为成员变量,而成员变量又包括实例变量和静态变量,当成员 变量声明时使用了 static 关键字,那么这种变量称为静态变量,没有使用 static 关键字称为实 例变量,实例变量是对象级别的,每个对象的实例变量值可能不同,所以实例变量必须先创建 对象,通过“引用”去访问,而静态变量访问时不需要创建对象,直接通过“类名”访问。实 例变量存储在堆内存当中,静态变量存储在方法区当中。实例变量在构造方法执行过程中初始 化,静态变量在类加载时初始化。类变量(类属性)由该类的所有实例共享。方法区存储的数据:类的加载信息、 静态变量、常量。

代码示例

public class Student {

    private int id; // 学号
    private String name; // 姓名
    private int age; // 年龄
    static String room; // 所在教室
    private static int idCounter = 0; // 学号计数器,每当new了一个新对象的时候,计数器++

    public Student() {
        this.id = ++idCounter;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

定义测试类


/*
如果一个成员变量使用了static关键字,那么这个变量不再属于对象自己,而是属于所在的类。多个对象共享同一份数据。
 */
public class Demo01StaticField {

    public static void main(String[] args) {

        Student two = new Student("黄蓉", 16);
        two.room = "101教室";
        System.out.println("姓名:" + two.getName()
                + ",年龄:" + two.getAge() + ",教室:" + two.room
                + ",学号:" + two.getId());//姓名:黄蓉,年龄:16,教室:101教室,学号:1

        Student one = new Student("郭靖", 19);
        System.out.println("姓名:" + one.getName()
                + ",年龄:" + one.getAge() + ",教室:" + one.room
                + ",学号:" + one.getId());//姓名:郭靖,年龄:19,教室:101教室,学号:2
    }

}

静态方法

  • 没有对象的实例时,可以用类名.方法名()的形式访问由static修饰的类方法。 static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。方法在什么情况下会声明为静态的呢?方法实际上描述的是行为动作,我认为当某个动作 在触发的时候需要对象的参与,这个方法应该定义为实例方法,例如:每个玩篮球的人都会打 篮球,但是你打篮球和科比打篮球最终的效果是不一样的,显然打篮球这个动作存在对象差异 化,该方法应该定义为实例方法。再如:每个高中生都有考试的行为,但是你考试和学霸考试 最终的结果是不一样的,一个上了“家里蹲大学”,一个上了“清华大学”,显然这个动作也 是需要对象参与才能完成的,所以考试这个方法应该定义为实例方法。以上描述是从设计思想角度出发来进行选择,其实也可以从代码的角度来进行判断,当方法体中需要直接访问当前对象的实例变量或者实例方法的时候,该方法必须定义为实例方法, 因为只有实例方法中才有 this,静态方法中不存在 this。在实际的开发中,“工具类”当中的方法一般定义为静态方法,因为工具类就是为了方便大家的使用,将方法定义为静态方法,比较方便调用,不需要创建对象,直接使用类名 就可以访问。

代码示例

public class MyClass {

    int num; // 成员变量
    static int numStatic; // 静态变量

    // 成员方法
    public void method() {
        System.out.println("这是一个成员方法。");
        // 成员方法可以访问成员变量
        System.out.println(num);
        // 成员方法可以访问静态变量
        System.out.println(numStatic);
    }

    // 静态方法
    public static void methodStatic() {
        System.out.println("这是一个静态方法。");
        // 静态方法可以访问静态变量
        System.out.println(numStatic);
        // 静态不能直接访问非静态【重点】
//        System.out.println(num); // 错误写法!

        // 静态方法中不能使用this关键字。
//        System.out.println(this); // 错误写法!
    }

}

定义测试类


/*
一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。

如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它。

无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()

注意事项:
1. 静态不能直接访问非静态。
原因:因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
“先人不知道后人,但是后人知道先人。”
2. 静态方法当中不能用this。
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。
 */
public class Demo02StaticMethod {

    public static void main(String[] args) {
        MyClass obj = new MyClass(); // 首先创建对象
        // 然后才能使用没有static关键字的内容
        obj.method();

        // 对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用。
        obj.methodStatic(); // 正确,不推荐,这种写法在编译之后也会被javac翻译成为“类名称.静态方法名”
        MyClass.methodStatic(); // 正确,推荐

        // 对于本来当中的静态方法,可以省略类名称
        myMethod();
        Demo02StaticMethod.myMethod(); // 完全等效
    }

    public static void myMethod() {
        System.out.println("自己的方法!");
    }

}

代码块

一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块 。(static block),没有使用static修饰的,为非静态代码块。

静态代码块 语法格式 是这样的:
 

静态代码块在类加载时执行,并且只执行一次。开发中使用不多,但离了它有的时候还真 是没法写代码。静态代码块实际上是 java 语言为程序员准备的一个特殊的时刻,这个时刻就 是类加载时刻,如果你想在类加载的时候执行一段代码,那么这段代码就有的放矢了。例如我们要在类加载的时候解析某个文件,并且要求该文件只解析一次,那么此时就可以把解析该文 件的代码写到静态代码块当中了。

静态代码块:用 static 修饰的代码块
  • 可以有输出语句。
  • 可以对类的属性、类的声明进行初始化操作。
  • 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
  • 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  • 静态代码块的执行要先于非静态代码块。
  • 静态代码块随着类的加载而加载,且只执行一次
代码示例
public class Person {

    static {
        System.out.println("静态代码块执行!");
    }

    public Person() {
        System.out.println("构造方法执行!");
    }

}

定义测试类

/*
静态代码块的格式是:

public class 类名称 {
    static {
        // 静态代码块的内容
    }
}

特点:当第一次用到本类时,静态代码块执行唯一的一次。
静态内容总是优先于非静态,所以静态代码块比构造方法先执行。

静态代码块的典型用途:
用来一次性地对静态成员变量进行赋值。
类加载的时候解析某个文件,并且要求该文件只解析一次
 */
public class Demo04Static {

    public static void main(String[] args) {
        Person one = new Person();
        Person two = new Person();
    }

}

代码执行结果

静态原理图解

static 修饰的内容:

  • 是随着类的加载而加载的,且只加载一次。
  • 存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
  • 它优先于对象存在,所以,可以被所有对象共享。

                                                           

总结一下:

  • 静态方法可以直接访问类变量和静态方法。
  • 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。
  • 静态方法中,不能使用this关键字。
  • 一个类当中可以编写多个静态代码块(尽管大部分情况下只编写 一个),并且静态代码块遵循自上而下的顺序依次执行,所以有的时候放在类体当中的代码是 有执行顺序的(大部分情况下类体当中的代码没有顺序要求,方法体当中的代码是有顺序要求 的,方法体当中的代码必须遵守自上而下的顺序依次逐行执行),另外静态代码块当中的代码 在 main 方法执行之前执行,这是因为静态代码块在类加载时执行,并且只执行一次。
  • 静态代码块在类加载时执行,静态变量在类加 载时初始化,它们在同一时间发生,所以必然会有顺序要求,如果在静态代码块中要访问 静态变 量,那么 静态变量必须放到静态代码块之前。

非静态代码块:没有static修饰的代码块

  • 可以有输出语句。
  • 可以对类的属性、类的声明进行初始化操作。
  • 除了调用非静态的结构外,还可以调用静态的变量或方法。
  • 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  • 每次创建对象的时候,都会执行一次。且先于构造器执行。
总结:程序中成员变量赋值的执行顺序
 
                                                                                              
 

final

Java 中声明 类、变量和方法 时,可使用关键字 final 来修饰 , 表示“最终的”。 final 标记的类不能被继承。 提高安全性,提高程序的可读性。 例如:String类、 System 类、 StringBuffer 类 。 final 标记的方法不能被子类重写。 比如:Object 类中的 getClass() final 标记的变量 ( 成员变量或局部变量 ) 即称为常量。 名称大写,且只 能被赋值一次 。 final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋 值,然后才能使用,例如:final double MY_PI = 3.14。
 
final修饰类
 
查询 API 发现像 public final class String public final class Math public final class Scanner 等,很多我们学习过的类,都是被fifinal 修饰的,目的就是供我们使用,而不让我们所以改变其内容。
 
/*
当final关键字用来修饰一个类的时候,格式:
public final class 类名称 {
    // ...
}

含义:当前这个类不能有任何的子类。(太监类)
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子。)
 */
public final class MyClass /*extends Object*/ {

    public void method() {
        System.out.println("方法执行!");
    }

}
final修饰方法
 
/*
当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写。
格式:
修饰符 final 返回值类型 方法名称(参数列表) {
    // 方法体
}

注意事项:
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
 */
public abstract class Fu {

    public final void method() {
        System.out.println("父类方法执行!");
    }

    public abstract /*final*/ void methodAbs() ;

}

修饰变量(基本类型的局部变量)

基本类型的局部变量,被 fifinal 修饰后,只能赋值一次,不能再更改。代码如下:
 

修饰变量(引用类型的局部变量)

引用类型的局部变量,被 fifinal 修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,代码如下:
 

修饰成员变量

成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:

public class User {
    //显示初始化;
    final String USERNAME = "张三";
    final int age;

    public User(int age) {
        //  构造方法初始化。
        this.age = age;
    }
}

 

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战,可谓是杀敌无数,见怪不怪了!在某知识社交平台中,一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读,可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表:零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时,为空表。 在比较复杂的线性表中,一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言,按照其应用领域,可以粗略地分成三类。 有的语言是多面手,在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类,比如说 C,Java, Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后,该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情,很多情况下,他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言,首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图: 上码: 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况,重点关注在中国市场扮演重要角色的全球及本土铪生产商,呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外,针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…