关于 static 和 final 的一些理解

---恢复内容开始---

今天主要回顾一下 static 和 final 着两个关键字。

1. static  -  静态

修饰符 - 用于修饰数据(变量、对象)、方法、代码块以及内部类。

    1.1 静态变量

用static修饰变量,称之为静态变量,也叫类变量。在类加载的时候加载到了方法区,并且在方法区中被赋予了默认值。静态变量是先于对象出现的,所以习惯上是通过类名来调用静态变量。每一个对象存储的是这个静态变量在方法区中的地址,所以静态变量是被这个类的所有对象所共享的。

静态变量能否定义到构造方法中? --- 不能。静态变量是在类加载的时候出现,先于对象出现。构造方法在创建对象的时候执行。

注意:

1.类是加载到方法区中的

2.类是在第一次使用的时候才加载,加载之后就不会移除

练习:定义一个类,统计这个类创建对象的个数。

package cn.tedu.staticx;

public class StaticExer {
    public static void main(String[] args) {
        new SDemo();
        new SDemo();
        new SDemo();
        System.out.println(SDemo.count);
    }
}

class SDemo{
    static int count = 0;//如果不用 static 则每一个对象创建的时候,都会赋值为 0 ,然后再加一次,只能是1
    public SDemo(){
        count++;
    }
}

   1.2 静态方法

用 static 修饰的方法,称之为静态方法。静态方法随着类的加载而加载到方法区中,但是在方法区中不执行只存储,在方法被调用的时候到栈内存执行。静态方法先于对象存在,所以习惯上是通过类名来调用静态方法。

main    Arrays.sort();   System.arraycopy();

静态方法中可以定义静态变量吗? --- 不能 --- 静态方法在调用的时候执行,静态方法执行的时候里面的变量才能初始化;静态变量是在类加载的时候初始化。

静态方法中能否使用 this/super? --- 不能 --- this 代表当前在活动的对象,静态方法先于对象存在

能否在静态方法中直接使用本类中的非静态方法/非静态属性? --- 不行

静态方法可以重载吗? --- 可以(讲重载的时候,默认都是写的 public static )

静态方法可以被继承吗?--- 可以

静态方法可以重写吗?--- 不可以

静态方法虽然不能被重写,但是父子类中可以存在方法签名一致的静态方法 --- 静态方法的隐藏(hide)

注意:父子类中可以存在方法签名一致的方法,要么都是非静态(重写)要么都是静态(隐藏)

package cn.tedu.staticx;

public class StaticDemo5 {
    public static void main(String[] args) {
        System.out.println(D.i);
    }
}

class D{
    static int j = 5;//先将静态变量i放入方法区,并且标记一个值为0;在初始化阶段,再检查i是否有初始值0,如果没有初始值,则将标记值0赋值进去;
                    //如果有初始值,则将初始值设置进去,抛弃标记值,然后顺次执行静态代码块,将静态变量i的值改为7
    {
        j = 7;
    }

        //在类加载阶段,由于i处于一个标记值状态,所以实际上是无值的,所以此时不允许直接操作
    static{      //先将静态变量i放入方法区,并且标记一个值为0;在初始化阶段,先执行静态代码块,对于i=7;并不是将7直接赋值给i;检查i是否有初始值,
                //如果没有初始值,则将标记值7赋值进去;如果有初始值则抛弃标记值,将初始值5赋值进去
        i = 7;
        i = 9;
        //i -= 5;//进行运算就报错了,类在加载的时候是分了 5 个阶段:准备(加载这个类中的静态变量并标记默认值) -> 初始化(初始化静态变量,执行静态代码块)
    }
    static int i = 5;
}

1.3 静态代码块

用static{ }包起来的代码 --- 在类加载的时候执行一次

执行顺序:父类静态 -> 子类静态 -> 父类非静态 -> 父类的构造方法 -> 子类非静态 -> 子类的构造方法

2. final

修饰符 --- 修饰数据、方法以及类

final 修饰数据的时候 ---- 常量 ->定义好之后不可改变。如果 final 修饰的是基本数据类型的数据,那么指的是实际值不可变;如果 final 修饰的引用类型的数据,那么指的是地址不可变,但是对象中的元素或者属性值可以改变 --- 对于成员常量要求在对象创建完成之前给值;对于静态常量而言要求在类加载完成之前给值。

arr.length    System.in    System.out

注意:常量的存储和方法区中的运行时常量池有关。

final修饰方法 --- 最终方法,能被继承但是不可被重写/隐藏,能被重载

final修饰类 --- 最终类  ---  不能被继承(里面的方法现阶段也不能被重写)System

package cn.tedu.finalx;

import java.util.Arrays;

public class FinalDemo1 {
    public static void main(String[] args) {

        //final int i = 9;
        final int i;
        i = 13;

        final int[] arr = {3,6,1,7,0};
        arr[1] = 8;//并没有报错,因为 arr 是一个对象 -> 地址不可变
        //arr = new arr[4];//报错了,地址改变了

        //arr.length = 9;

        //changeValue(i);
        System.out.println(i);

        expand(arr);//一开始主函数中有一个 arr 了,指向堆内存中的某个地址,当调用这个方法后,方法中的 arr 会指向这个地址,但改变后,
        System.out.println(arr.length);//方法中的arr指向新的地址,而主函数中的那个还是指向原来的地址(方法用完就释放堆内存中的资源)
    }

    //在这个方法中并没有将参数i定义为常量
    public static void changeValue(int i){
        i++;
    }

    public static void expand(int[] arr){
        arr = Arrays.copyOf(arr, arr.length * 2);
    }
}

class A{

    //定义成员常量
    //成员常量 i 在对象完成创建之前给值
    final int i = 6;
    int j;

    //静态常量必须在类加载完成之前给值
    static final int k = 0;

    {
        //i = 10;
    }

    public A(){
        //i = 10;
    }
}

/*class A{

    private final int i;

    {
        //i = 4;
    }

    public A(){
        this(5);//是对的
        //this.i = 0;也是对的,两次调用是互不影响的
    }//无参构造中未初始化常量
    public A(int i){
        this.i = i;//常量的二次赋值
    }
}

*/

---恢复内容结束---

原文地址:https://www.cnblogs.com/tangdiao/p/9460531.html

时间: 2024-10-19 23:15:17

关于 static 和 final 的一些理解的相关文章

JAVA Static方法与单例模式的理解

近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对static方法与单例模式的理解. 所谓单例模式,我不做过多解释,推荐java设计模式之禅这本书,好好理解一下. 这里我谈谈两种写法: 曾经一些公共的类,我不假思索,习惯依照例如以下写法去写: public class DateUtil { public final static String DAT

java中static,super,final关键字辨析

1:static关键字 利:1)对对象的共享数据提供单独的空间存储. 2)修饰的方法可以直接被类名调用 弊:1)生命周期长. 2)访问出现限制(只能访问静态) 它可以有静态方法,静态类,静态变量 2:super关键字 1)使用super关键字调用父类的成员变量和成员方法. 格式1:super.成员变量 格式2:super.成员方法([参数1,参数2...]) 2)使用super关键字调用父类的构造方法 格式1:super([参数1,参数2...]) 总结:this代表当前对象(可以输出或地址).

对final关键字的理解

http://www.cnblogs.com/xrq730/p/4820296.html 一直想写写这个话题.代表公司也面试过一些求职者,每次面试我必问的两个问题之一 就是“请你谈一谈对于final关键字的理解”.这是一个简单的小问题,但是不要小看它,通过对这个问题的回答以及一些简单的扩展就能看出一个求职者的基 础是否扎实以及是否有钻研精神.OK,开始进入主题. 相信对于final的用法,大多数人都可以随口说出三句话: 1.被final修饰的类不可以被继承 2.被final修饰的方法不可以被重写

JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配

Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放.堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据.但缺点是,由于要在运行时动态分配内存,存取速度较慢. 栈的优势是

Java中static、final用法

一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变.其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中.这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值. 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的

Java中static、final用法小结(转)

一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变.其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中.这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值. 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的

Java中的内存处理机制和final、static、final static总结

Java中的内存处理机制和final.static.final static总结 装载自:http://blog.csdn.net/wqthaha/article/details/20923579 Java程序运行在JVM上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提.         一个完整的Java程序运行过程会涉及以

Android中static和final用法小结

Java关键字static.final使用小结 static  1. static变量 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量:另一种是没有被static修饰的变量,叫实例变量.两者的区别是: 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的).对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变

Java中static、final用法小结

一.final 1.final变量: 当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变.其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中.这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值. 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的