文章目录

  • 1. 前言
  • 2. 简介JVM内存模型的虚拟机栈,堆和方法区
  • 3.static
    • 2.1 为什么需要static?
    • 2.2 static修饰的属性、方法、代码块、内部类的特点
    • 2.2 static 属性
    • 2.3 static 方法
    • 2.4 static的属性和方法在父类与子类之间的继承和重写关系
    • 2.5 static代码块与非static代码块
    • 2.6 程序中成员变量赋值的执行顺序
    • 2.7 静态内部类
  • 4.static与main
    • 4.1 static与main方法简介
    • 4.2 面试题
  • 5.final
    • 5.1 final 修饰变量—— 常量
    • 5.2 final修饰类
    • 5.3 final修饰方法
    • 5.4 static final---全局常量
    • 5.5 面试题

本篇文章已同步到:https://www.bithachi.cn/posts/725e9ca.html

1. 前言

  • 本篇文章主要介绍Java语言中的两大关键字satic和final,还有main方法与static的渊源
  • static的中文意思是静态的,final的中文意思是最终的,不可更改的。

我们将从以下三大主线讲解:

  1. static 修饰属性、方法、代码块、内部类
  2. main 方法与 static 的渊源
  3. final 修饰类、变量和方法

2. 简介JVM内存模型的虚拟机栈,堆和方法区

这里只介绍虚拟机栈,堆和方法区,因为这篇文章需要使用到。

  • 通常所说的栈(Stack) ,是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double ),对象引用( reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完, 自动释放,从栈中弹出。

  • 堆(Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配

  • 方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

3.static

2.1 为什么需要static?

  • 有时候我们想要让所有同一个类的实例对象共享同一个数据,那么我们就需要用到类变量,也就是static修饰的变量。
  • 这个数据可以是属性、方法、代码块、内部类

2.2 static修饰的属性、方法、代码块、内部类的特点

  1. 随着类的加载而加载;无论是否产生对象,static修饰的属性、方法、代码块、内部类都会在JVM内存区的方法区存在一份
  2. 优先于对象存在,类加载时static域已经在内存中加载了,加载到了JVM内存的方法区
  3. 修饰的成员,被同一个类实例的所有对象共享
  4. 访问权限允许时,可不创建对象,直接被类调用,即通过类名访问static修饰的成员,classname.staticmember

2.2 static 属性

  • static修饰的类变量(类属性)由该类的所有实例共享
  • static修饰的属性可以被继承
  • 当某一个实例改变了static修饰的属性的值时,其它实例变量使用时是修改后的值,如下图所举例子所示:

2.3 static 方法

  • static修饰的方法简称类方法

  • 没有对象的实例时,可以用 类名. 方法名()的形式访问由static修饰的类方法。

  • static 方法内部只能访问类的static 修饰的属性或方法, 不能访问类的非static 的结构

  • 因为不需要实例就可以访问static 方法,因此static 方法内部不能有this 。当然也不能有super

  • static修饰的方法不可以重写,重写的定义是:方法名、返回值类型、参数列表 与父类中某个方法一样。经检验子类必须写的和父类一模一样加static才可以覆盖static方法,而这不满足重写的定义,所以不能叫重写

  • static修饰的属性和方法可以继承,可以使用子类类名访问,但是不能通过子类对象访问。

2.4 static的属性和方法在父类与子类之间的继承和重写关系

下面一个例子测试了static的属性和方法在父类与子类之间的继承和重写关系:

public class Person {public static String s="Person";//测试重写public static void display() {//测试重写System.out.println("Person display");}public static String ss="Person two"; //测试继承性public static void displayPerson() {测试继承性System.out.println("Person displayPerson");}
}
public class Man extends Person {public static String s="Man";public static void display() {//将static去掉报错System.out.println("Man display");}private static int total = 0;private int id=0;public Man() {total++;}public static int getTotalPerson() {//id++; //静态方法不能访问非静态属性和方法//displayA();//this.total=10;//this.id=10;return total;}}
public class TestMain {public static void main(String[] args) {/************  打印Person的属性和方法做对比  ************/System.out.println(Person.s);System.out.println(Person.ss);Person.display();Person.displayPerson();System.out.println("---------");/************  测试继承性  ************/System.out.println(Man.ss);Man.displayPerson();System.out.println("---------");/************  测试重写性  ************/System.out.println(Man.s);Man.display();/************  测试多态性  ************/Person p=new Man();//不能调用Person和Man的任何属性方法,只能调用Object的属性和方法Man mm=new Man();//mm不能访问Person的static属性和static方法System.out.println("---------");System.out.println("total is " + Man.getTotalPerson());Man p1 = new Man();//执行构造器total+1System.out.println("total is " + Man.getTotalPerson());}
}

运行结果:

Person
Person two
Person display
Person displayPerson
---------
Person two
Person displayPerson
---------
Man
Man display
---------
total is 1
total is 2

2.5 static代码块与非static代码块

既然已经说到了代码块,那么就一次性把静态和非静态代码块一次性尽量总结完叭

  • 代码块(或初始化块)的作用:
    对Java 类或对象进行初始化
  • 代码块(或初始化块)的分类:
    一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块(static block),没有使用static修饰的,为非静态代码块
  • static 代码块化 通常用于初始化static
class Person {public static int total;
static {total = 100;// 为total 赋初值
}
…… //其它属性或方法声明
}

静态代码块:用static 修饰的代码块

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
  4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  5. 静态代码块的执行要先于非静态代码块。
  6. 静态代码块随着类的加载而加载,且只执行一次

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

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 除了调用非静态的结构外,还可以调用静态的变量或方法。
  4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  5. 每次创建对象的时候,都会执行一次。且先于构造器执行
  • 静态代码块不可以继承,只随类的加载执行一次
  • 非静态代码块可继承,每次创建对象的时候,都会执行一次。且先于构造器执行

下面看个例子:

public class Person {Person(){System.out.println("person construct");}public int a=1,b=1;{//`每次创建对象的时候,都会执行一次。且先于构造器执行`a++;int x=20;int b=2;{//            int b=2;//不能在嵌套的两个{{}}定义相同的变量a++;}a++;System.out.println("no static Person a="+a);}public  static int c=1,d=1;static{//`静态代码块随着类的加载而加载,且只执行一次`c++;int b=2;int yy=20;{//            int b=2;//不能在嵌套的两个{{}}定义相同的变量c++;}c++;System.out.println("static Person c="+c);}}
public class Man extends Person {Man(){this.a=10;//不能this.c this.dthis.b=10;System.out.println("Man a="+a);System.out.println("Man b="+b);}}
public class TestMain {public static void main(String[] args) {Person p=new Person();System.out.println("-----------");Man m=new Man();System.out.println("---------");System.out.println(Man.c);System.out.println(Man.d);System.out.println(m.a);System.out.println(m.b);//没有m.c m.d//m.xx 报错,就像方法里面的局部变量一样不可以使用对象或类名访问}
}

运行结果:

static Person c=4
no static Person a=4
person construct
-----------
no static Person a=4
person construct
Man a=10
Man b=10
---------
4
1
10
10

2.6 程序中成员变量赋值的执行顺序

2.7 静态内部类

  • 关于静态内部类可参考此篇文章里面写到的静态内部类:https://www.bithachi.cn/posts/bf7b3e18.html

4.static与main

4.1 static与main方法简介

  • 由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。

  • 因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。

命令行参数用法举例:

public class CommandPara {public static void main(String[] args) {for (int i = 0; i < args.length; i++) {System.out.println("args[" + i + "] = " + args[i]);}}
}

4.2 面试题

此处,Something类的文件名叫OtherThing.java
class Something {public static void main(String[] something_to_do) {System.out.println("Do something ...");
}
}
上述程序是否可以正常编译、运行?

答案是可以正常编译执行

5.final

在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。

  1. final 标记的类不能被继承 。提高安全性,提高程序的可读性。
    String类、System类、StringBuffer类
  2. final 标记的方法不能被子类重写。
    比如:Object类中的getClass()。
  3. final 标记的变量( 成员变量或局部变量) 即称为常量 。名称大写,且只能被赋值一次。
  4. final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用。
    final double MY_PI = 3.14;

5.1 final 修饰变量—— 常量

class A {private final String INFO = "BitHachi"; //声明常量public void print() {//The final field A.INFO cannot be assigned//INFO = "Hachi";//Error}
}

5.2 final修饰类

final class A{}
class B extends A{ //错误,不能被继承。
}

5.3 final修饰方法

class A {public final void print() {System.out.println("A");}
}
class B extends A {public void print() { // 错误,不能被重写。System.out.println("B");}
}

5.4 static final—全局常量

  • static final:全局常量
  • static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。
  • static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问

5.5 面试题

面试一:

public class Something {public int addOne(final int x) {return ++x;//Error// return x + 1;//OK}
}
调用addOne方法时,不能对final常量改变值,只能使用其值

面试二:

public class Something {public static void main(String[] args) {Other o = new Other();new Something().addOne(o);
}
public void addOne(final Other o) {// o = new Other();//o是常量不可以再变o.i++;//i是变量可以变
}
}
class Other {public int i;
}

一篇文章全方位了解:static main final相关推荐

  1. 一篇文章让你全方位掌握git版本控制管理

    注:侵权请联系作者删除 目录 1.引入: 2.Git 的工作区域和流程 3.stash区域 4.git基本操作 A.git add B.git commit c.git pull D.git fetc ...

  2. Android:学习AIDL,这一篇文章就够了(上)

    前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说--你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓--那样就很尴尬了.不过又转念一想, ...

  3. 一篇文章教你学会使用SpringBoot实现文件上传和下载

    文章目录 一.搭建SpringBoot开发环境 1.创建项目 2.配置application.properties参数 3.实体响应类和异常信息类 4.创建FileController 二.接口测试 ...

  4. 集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(离线)

    原址 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(在线) 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合)     ...

  5. 一篇文章让你从JAVA零基础入门`OOP`编程12.19

    一篇文章让你从JAVA零基础入门OOP编程 前言: 此文为玄子,复习ACCP-S1课程后,整理的文章,文中对知识点的解释仅为个人理解. 配套PPT,站点源码,等学习资料 一.预科 1.1 JAVA 介 ...

  6. java学到能看懂代码_一篇文章能够看懂基础源代码之JAVA篇

    一篇文章能够看懂基础源代码之JAVA篇 发布时间:2020-05-19 11:20:32 来源:51CTO 阅读:305 作者:栖木之地 java程序开发使用的工具类包:JDK(java develo ...

  7. 一篇文章看明白 Android PackageManagerService 工作流程

    Android - PackageMangerService 分析 相关系列 一篇文章看明白 Android 系统启动时都干了什么 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制 ...

  8. 一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系

    Android - SurfaceFlinger 图形系统 相关系列 一篇文章看明白 Android 系统启动时都干了什么 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制 一篇文 ...

  9. 一篇文章让你从JAVA零基础入门`OOP`编程12.20

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(QQ_3336392096.png)] 一篇文章让你从JAVA零基础入门OOP编程 前言: 此文为玄子,复习ACCP-S1课程后, ...

最新文章

  1. android p wifi一直在扫描_Android再次解读萤石云视频
  2. 【Java】浅析八种基本类型
  3. AjaxFileUpload.js
  4. 基于Android Classic Bluetooth的蓝牙聊天软件
  5. Windows Terminal Preview v0.4 发布,微软出品的全新终端
  6. pythonenumapi_python模块之enum_上
  7. 淡入淡出效果 (jQuery)
  8. Atitit 信用卡与会员卡(包括银行卡)的发展之路
  9. 动软代码生成器连不上高版本(8.0+)的解决方法
  10. 使用adb命令启动模拟器
  11. 我们的后花园需要如何保护
  12. 360极速模式版本,出现已经取消网页导航现象,怎么解决呢?
  13. 数学工具-desmos 图形曲线
  14. 使用Scrapy框架爬取58同城的出租房信息
  15. 银行大数据应用场景:客户画像如何做?
  16. wpf listview透明但字不要透明_早春松树松针上出现透明液体,不要不在意,可能是松大蚜在危害...
  17. 经典语录-2014330
  18. 计算机基础教学质量分析报告,张丹菲信息技术质量分析报告1
  19. php 生日还剩多少天,请教PHP中计算离生日还剩下多少天问题?
  20. java jfif_Java文件类型工具类

热门文章

  1. js获取时间段内属于星期一的日期们
  2. 如何在CentOS 7上安装Redis服务器
  3. Asp.Net Core MVC控制器和视图之间传值
  4. 一篇小的随笔,关于记忆算法和概念
  5. 目标跟踪_MeanShift
  6. Inspector a ProgressBar(定制属性面板)
  7. hdu 1251 统计难题(字典树)
  8. iscroll.js 触屏手机web-kit浏览器滚动效果代码库
  9. favorites 不是一个有效的短文件名
  10. 你看我还有机会吗?这么GAN让我秃然荒了!