static和final关键字
static关键字
静态变量
- 静态变量:又称做类变量,也就是这个变量属于整个类,而不属于单个实例。类所有的实例共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份,当系统第一次加载类时,系统为静态变量分配内存,直到该类不在使用,内存才会被回收,生命周期几乎等同于该类的生命周期。
- 实例变量:每创建一个实例就会产生一个实例变量,与该实例同生共死。
public class A {
private int x; //实例变量
private static int y; //静态变量
public static void main(String[] args) {
A a = new A();
//实例变量,只能通过实例来访问
System.out.println(a.x); //0
//静态变量属于类本身,所以既可以通过实例也可以通过类本身来访问
System.out.println(a.y); //0
System.out.println(A.y); //0
//更改静态变量和实例变量的值
a.x = 10;
a.y = 5;
A b = new A();
//静态变量只创建一次,被所有实例共享,实例变量仅属于实例本身
System.out.println(b.x); //0
System.out.println(b.y); //5
}
}
静态方法
静态方法:又称做类方法,在类加载的时候就存在了,它不依赖于任何实例,可以通过类名来访问。静态方法必须有实现,不能是抽象方法,只能访问所属类的静态成员和静态方法,不能出现 this 和 super 关键字,因为该方法不依赖任何实例就可以访问,而实例变量或者方法必须先创建实例才能访问。
public class A {
private int x; //实例变量
private static int y; //静态变量
//main方法本身就是静态方法
public static void main(String[] args) {
//int a = x; 报错
int b = y;
System.out.println(b); //0
}
}
静态代码块
静态代码块:仅在类第一次被加载时运行一次的代码块,可用于对静态变量初始化。
public class A {
static {
System.out.println("hello word!");
}
public static void main(String[] args) {
A a = new A();
A b = new A();
}
}
//输出:hello word!
静态内部类
静态内部类:非静态内部类必须依赖外部类的实例,而静态类不需要,直接通过外部类名来创建。静态内部类不能访问外部类的非静态的变量和方法。
public class A {
public class InnerClass{
}
public static class StaticInnerClass {
}
public static void main(String[] args) {
A a = new A();
//非静态内部类的创建,必须依赖外部类的实例
InnerClass innerClass = a.new InnerClass();
//静态内部类的创建
StaticInnerClass staticInnerClass = new A.StaticInnerClass();
}
}
初始化顺序
静态变量声明和静态语句块优先于实例变量声明和普通语句块,静态变量声明和静态语句块的初始化顺序取决于它们在代码中的顺序,最后才是构造函数的初始化。
存在继承情况下的初始化顺序,括号内容的执行顺序取决于在代码的顺序:
- 父类(静态变量声明、静态语句块)
- 子类(静态变量声明、静态语句块)
- 父类(实例变量声明、普通语句块)
- 父类(构造方法)
- 子类(实例变量声明、普通语句块)
- 子类(构造方法)
顺序规则:第一次加载类(还未创建对象)时,从最顶层父类开始执行静态变量声明、静态语句块(执行顺序与代码顺序有关);当真正创建对象时,从最顶层父类开始执行实例变量声明、普通语句块和构造方法(前面两个先执行,执行顺序与代码顺序有关,构造方法最后执行),只有父类成员初始化完毕,才会初始化子类成员。
class Father {
{
System.out.println("father普通代码块");
}
static {
System.out.println("father静态代码块");
}
public Father() {
System.out.println("father构造方法");
}
}
public class Son extends Father{
{
System.out.println("son普通代码块");
}
static {
System.out.println("son静态代码块");
}
public Son() {
System.out.println("som构造方法");
}
public static void main(String[] args) {
new Son();
}
}
/*输出:
father静态代码块
son静态代码块
father普通代码块
father构造方法
son普通代码块
som构造方法
*/
final关键字
数据
声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。
- 对于基本类型,final 使数值不变;
- 对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的。
final int x = 1;
//x = 2; //报错,基本类型不能更改
final A a = new A();
a.c = 1; //正常运行,引用变量不能更改引用对象,但可以更改对象数据
数据可分为成员变量和局部变量,两种都可以加 final。
成员变量
final 修饰的成员变量必须显示赋初始值。
不管是静态变量还是实例变量,在分配内存时,会先分配默认值(0,\u0000,false 或 null)。当执行静态代码块或者静态变量声明时可对静态变量显示赋初始值;当执行普通代码块、实例变量声明或者构造器时可对实例变量显示赋初始值。如果变量没有显式赋初始值,变量初始值使用默认值。而被 final 修饰的成员变量使用默认值将毫无意义,所有规定 final 修饰的成员变量必须显示赋初始值。
public class A{
static {
//此处代码块比声明执行顺序更早,所以A.a还未赋初始值,为0
//A.b由final修饰,必须有初始值,所以此处先查询声明是否赋初始值,再运行,为10
System.out.println(A.a); //0
System.out.println(A.b); //10
}
private static int a = 10;
private static final int b = 10;
private final int c;
//private final int d; //没有赋初始值报错
public A() {
c = 10;
}
public static void main(String[] args) {
new A();
}
}
局部变量
public void test(final int a) {
//a = 5; //报错,不能对final修饰的形参赋值
}
public static void main(String[] args) {
final String str = "hello";
//str = "Java"; //报错,不能再赋值
final double d;
d = 5.6; //正常运行,局部变量没有默认值,必须显示赋初始值
}
方法
被 final 修饰的方法不能被子类重写。private 方法被隐式地指定为 final,如果在子类中定义的方法和父类中的一个 private 方法签名相同,不是重写父类方法,而是定义了一个新的方法。
class B {
public final void f1() {
}
private void f2() {
}
}
public class A extends B {
public void f1() { //报错
}
private void f2() { //正常
}
}
类
被 final 修饰的类不能被继承。
final class B {
}
public class A extends B { //报错
}
static和final关键字的更多相关文章
- Java的static和final关键字的用法
static关键字的用法 static的意思是"'静态的",在java里面可用于修饰属性和方法. static关键字的应用应注意以下几种情形: 1.static作用于某个字段,一个 ...
- static 和 final 关键字 对实例变量赋初始值的影响
static 和 final 关键字 对实例变量赋初始值的影响 最近一直在看<深入理解Java虚拟机>,在看完了对象内存分配.Class文件格式之后,想深扒一下实例变量是如何被赋上初始值的 ...
- JAVA面对对象(三)——Super、static、final关键字
Super 使用super关键字可以直接调用父类中的构造方法.属性.普通方法 super调用父类构造方法的操作,与this调用构造方法一样,语句必须放在子类构造方法的首行 public class P ...
- 【Java_基础】java中static与final关键字的区别
1.static关键字 经static关键字修饰的成员被该类的所有对象所共享,任意一对象对静态变量的修改其它对象都是可见的.通常通过类名来引用static成员.类加载的连接阶段将会为静态成员变量在jv ...
- java中static,super,final关键字辨析
1:static关键字 利:1)对对象的共享数据提供单独的空间存储. 2)修饰的方法可以直接被类名调用 弊:1)生命周期长. 2)访问出现限制(只能访问静态) 它可以有静态方法,静态类,静态变量 2: ...
- 关于static以及final关键字
Static关键字: 可以用来修饰类中的属性.类中的方法.以及具体的某一个类. 1.用于修饰属性: 则表示该属性属于整个类,不论有多少个对象实例,所有的实例共同拥有一个static静态的成员变量.该变 ...
- Java中的static、final关键字
static static 的含义是静态的,是一个静态修饰符,一般来说,被static修饰的有以下几种,类.变量.方法.代码块. static修饰类 Java中普通的类是不允许被声明为静态的,但是有一 ...
- java中的static和final关键字
一:static 1)修饰成员变量: static关键字可以修饰成员变量,它所修饰的成员变量不属于对象的数据结构,而是属于类的变量,通常通过类名来引用static成员. 当创建对象后,成员变量是存储在 ...
- static,final关键字,Object类的tostring方法,equals方法,hashCode方法
1)static关键字 static可以修饰:属性.方法.代码块 静态方法不能访问非静态 属性 或 方法 属性(变量): 成员变量: 静态变量: 通过 类名.静态变量来访问 通过 对象名.静态变量来访 ...
随机推荐
- C#面向对象--练习题
public class Program { //用户自定义:我们自己定义这种数据类型 public struct jiegouti// 结构体前面加上public, 可供外界访问 { public ...
- Unity5.6.4f1 配置WebGL教程
Unity 5.6.4f1 发布WebGL的配置教程 步骤一:先查看自带的Unity是否yi配置好WebGL的项,若无,则可遵循以下教程来设置 步骤二:下图是我已经设置好的,未设置好的状态是,有个Op ...
- vue+vant 购物车的全选和反选
https://blog.csdn.net/wjswangjinsheng/article/details/91392694
- el-table翻页序号不从1开始(已解决)
法一:赋值方式(亲测有效) <el-table-column type="index" fixed="left" align="center&q ...
- 2018-8-10-win10-uwp-绘图--Line-控件使用
title author date CreateTime categories win10 uwp 绘图 Line 控件使用 lindexi 2018-08-10 19:16:51 +0800 201 ...
- java 静态导入(1.5特性,好处是不用写类名)
import语句可以导入一个类或某个包中的所有类 import static语句导入一个类中的某个静态方法或所有静态方法 语法举例: import static java.lang.Math.sin; ...
- vue 弹窗时 监听手机返回键关闭弹窗(页面不跳转)
[注]: popstate 事件 a.当活动历史记录条目更改时,将触发popstate事件. b.如果被激活的历史记录条目是通过对history.pushState()的调用创建的,或者受到对his ...
- Java内存溢出java.lang.OutOfMemoryError: PermGen space
今天把以前的一个项目部署在tomcat,启动没问题.因为用到了webservice,当调用webservice中的方法时一直报内存溢出异常 Exception in thread "http ...
- JNI相关使用记录
JNI 工作流程 java层调用system.load方法. 通过classloader拿到了so文件的绝对路径,然后调用nativeload()方法. 通过linux下的dlopen方法,加载并查找 ...
- webpack 命令
--content-base <file/directory/url/port>:内容的路径. --quiet: 在控制台不输出任何内容 --no-info: 抑制无聊的信息 --colo ...