本篇文章主要分为两个模块进行介绍:1.final,staic,static final之间的异同;2. static 模块;3.嵌套类的概念

1.final,staic,static final之间的异同:

(1)final

final可以修饰属性,方法,类,局部变量(静态变量、实例变量和局部变量);

其中,final修饰的属性表明是个常量,它的初始化可以在编译期,也可以在运行期,初始化后不能被改变;

final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值;

final修饰的方法不能被子类方法覆盖,但可以被继承;

private不能被子类方法覆盖,private类型的方法默认是final类型的

final修饰的类不能被继承,没有子类,final类中的方法默认是final的

final不能用于修饰构造方法;

另外,对于基本类型数据,final会将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能再将句柄指向另一个对象。但是,对象的本身是可以修改的。这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的。方法参数中的final句柄,意味着在该方法内部,我们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值)。

(2)static

static表示“全局”或者“静态”的意思,可以用来修饰:属性,方法,代码段,内部类(静态内部类或嵌套内部类),static不可以修饰局部变量。
其中,static修饰的属性的初始化在编译期(类加载的时候),初始化后能改变,并且每个对象都只有一个值,主要强调它们只有一个。

static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static修饰的属性、方法等,

static和“this、super”势不两立,因为this、super正好跟具体对象有关。

也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

用public修饰的static属性和方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。
 其中:
- 类成员变量
  - 静态变量(类变量): static修饰
  - 实例变量  : 无static修饰
  - 局部变量 :(方法内部声明)

(3)static final(等价于final staic,但是一般习惯staic在前)

static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。static final也可以修饰方法,表示该方法不能重写,可以在不new对象的情况下调用

2.static{}代码块与普通{}代码块的区别

在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:

 //静态代码块
static {
语句序列
} //普通代码
{
语句序列
}

其中,静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。

静态代码块里面的变量都是局部变量,只在本块内有效。

静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。

一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。

静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。

例子1:

 public class staticBlock{
//定义一个普通的main()方法
public static void main(String args[]){
System.out.println("This is main method.");
}
//定义一个静态代码块
static{
System.out.println("This is static block.");
int stVar = 0; //这是一个局部变量,只在本块内有效
}
}

运行结果:

This is static block.
This is main method. 

从以上输出结果中可以看出,静态代码块甚至在main方法之前就被执行。在main()方法中可以完成的任务在静态代码块中都可以完成。但是二者在执行上仍然有一些区别。

例子2:

 public class staticBlock{
static int stMember = 100; //定义静态成员变量
public static void main(String args[]){
System.out.println("This is main method.");
}
//第一个静态代码块
static{
System.out.println("This is first static block.");
stMember = 200; //访问静态成员变量
staticBlock oa = new staticBlock(); //创建对象
System.out.println("stMember = " + oa.stMember);
statFun(); //调用静态方法
}
//定义一个静态方法
static void statFun(){
System.out.println("This is a static method.");
}
//第二个静态代码块
static{
System.out.println("This is second static block.");
}
}

运行结果如下:

This is first static block.
stMember = 200
This is a static method.
This is second static block.
This is main method.

静态代码块与普通代码块的差异如下:

相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,

    一般在代码块中对一些static变量进行赋值。

不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。

    静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new

    一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。

例子:

 //普通类
public class PuTong {
public PuTong(){
System.out.print("默认构造方法!-->");
} //非静态代码块
{
System.out.print("非静态代码块!-->");
} //静态代码块
static{
System.out.print("静态代码块!-->");
} public static void test(){
{
System.out.println("普通方法中的代码块!");
}
}
} //测试类
publicclass TestClass { /**
* 区别两次new静态与非静态代码块执行情况
*/
public static void main(String[] args) {
PuTong c1 = new PuTong();
c1.test(); PuTong c2 = new PuTong();
c2.test();
}
}

/*
运行输出结果是:
静态代码块!-->非静态代码块!-->默认构造方法!-->普通方法中的代码块!
非静态代码块!-->默认构造方法!-->普通方法中的代码块!
*/

一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的.

两者的区别就是:静态代码块是自动执行的;

静态方法是被调用的时候才执行的.

作用:静态代码块可用来初始化一些项目最常用的变量或对象;静态方法可用作不创建对象也可能需要执行的代码.

 

3.嵌套类概念

可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:
  其一、在一个类(外部类)中直接定义的内部类;
  其二、在一个方法(外部类的方法)中定义的内部类;
  其三、匿名内部类。

(1)静态嵌套类

 public class StaticTest {
private static String name = "javaJohn"; 
  private String id = "X001";
  static class Person{
    private String address = "swjtu,chenDu,China";
    public String mail = "josserchai@yahoo.com";//内部类公有成员
    public void display(){
      //System.out.println(id);//不能直接访问外部类的非静态成员
      System.out.println(name);//只能直接访问外部类的静态成员
      System.out.println("Inner "+address);//访问本内部类成员。
    }
  }   public void printInfo(){
    Person person = new Person();
    person.display();
    //System.out.println(mail);//不可访问
    //System.out.println(address);//不可访问
    System.out.println(person.address);//可以访问内部类的私有成员
    System.out.println(person.mail);//可以访问内部类的公有成员   }
  public static void main(String[] args) {
  StaticTest staticTest = new StaticTest();
  staticTest.printInfo();
}
}

在静态嵌套类内部,不能访问外部类的非静态成员,这是由Java语法中"静态方法不能直接访问非静态成员"所限定。若想访问外部类的变量,必须通过其它方法解决,由于这个原因,静态嵌套类使用很少。注意,外部类访问内部类的的成员有些特别,不能直接访问,但可以通过内部类来访问,这是因为静态嵌套内的所有成员和方法默认为静态的了。同时注意,内部静态类Person只在类StaticTest 范围内可见,若在其它类中引用或初始化,均是错误的。

(2)外部内中的内部类

  public class Outer {
  int outer_x = 100;
    class Inner{
      public int y = 10;
      private int z = 9;
      int m = 5;
      public void display(){
        System.out.println("display outer_x:"+ outer_x);
      }
      private void display2(){
        System.out.println("display outer_x:"+ outer_x);
      }
    }
    void test(){
      Inner inner = new Inner();
      inner.display();
      inner.display2();
      //System.out.println("Inner y:" + y);//不能访问内部内变量
      System.out.println("Inner y:" + inner.y);//可以访问
      System.out.println("Inner z:" + inner.z);//可以访问
      System.out.println("Inner m:" + inner.m);//可以访问
      InnerTwo innerTwo = new InnerTwo();
      innerTwo.show();
    }
    class InnerTwo{
      Inner innerx = new Inner();
      public void show(){
        //System.out.println(y);//不可访问Innter的y成员
        //System.out.println(Inner.y);//不可直接访问Inner的任何成员和方法
        innerx.display();//可以访问
        innerx.display2();//可以访问
        System.out.println(innerx.y);//可以访问
        System.out.println(innerx.z);//可以访问
        System.out.println(innerx.m);//可以访问
      }
    }
    public static void main(String args[]){
      Outer outer = new Outer();
      outer.test();
    }
  }

以上代码需要说明有,对于内部类,通常在定义类的class关键字前不加public 或 private等限制符,若加了没有任何影响,同时好像这些限定符对内部类的变量和方法也没有影响(?)。另外,就是要注意,内部类Inner及InnterTwo只在类Outer的作用域内是可知的,如果类Outer外的任何代码尝试初始化类Inner或使用它,编译就不会通过。同时,内部类的变量成员只在内部内内部可见,若外部类或同层次的内部类需要访问,需采用示例程序中的方法,不可直接访问内部类的变量。

3.在代码块的作用域内定义内部类。

 public class Outer {

     private String outerName = "This is Outer Name";

     public void test() {

         for(int i=0;i<3;i++) {
class Inner {
public void display() {
System.out.println(outerName);
}
}
Inner inner = new Inner();
inner.display();
}
}
}

在上面的代码中,只能定义成class inner,不能定义成public class inner,因为此时是作为方法中的变量定义的,不是作为类的成员变量。

参考链接:

https://blog.csdn.net/qq_40665031/article/details/78440084

https://blog.csdn.net/hust_yfang/article/details/79585696

https://www.cnblogs.com/EasonJim/p/7841990.html

https://blog.csdn.net/leixiongbo/article/details/52161936

https://blog.csdn.net/WelcomeSpring/article/details/79430546

 

final与 static的区别;static代码块以及嵌套类介绍的更多相关文章

  1. 13_java之final|static|包|匿名对象|代码块|内部类

    01final关键字概念 * A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承 ...

  2. Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案

    继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...

  3. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第6节 static静态_15_静态代码块

    static的特殊用法, 静态代码块 加上构造方法,做测试 又创建一个对象 静态代码块 只执行一次 后续在学习jdbc的时候,静态代码块很有用途.

  4. Python基础学习Day6 is id == 区别,代码块,小数据池 ---->>编码

    一.代码块 Python程序是由代码块构造的.块是一个python程序的文本,他是作为一个单元执行的. 代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块. 而作为交互方式输入的每个命令都是 ...

  5. static{}静态代码块与{}普通代码块之间的区别

    先看一个例子: //class A package com.my.test; class A { static { System.out.println("A1:父类静态代码区域" ...

  6. 5.1JAVA基础复习——JAVA中的静态代码块、构造代码块、构造函数、局部代码块区别

    构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...

  7. java静态类、静态方法、静态代码块,静态变量及实例方法,实例变量初始化顺序及内存管理,机制

    1.当一个类被第一次使用时,它需要被类加载器加载,而加载过程涉及以下两点: (1)在加载一个类时,如果它的父类还未被加载,那么其父类必须先被加载: (2)当类加载到内存之后,按照在代码中的出现顺序执行 ...

  8. final、static、代码块、静态代码块、内部类、代码执行顺序

    final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上               ...

  9. [Day13]static、final、匿名对象、内部类、包、修饰符、代码块

    1.final-最终 (1)final的特点 final修饰类不可以被继承,但是可以继承其他类 final修饰的方法不可以被覆盖,但父类中没有final修饰方法,子类覆盖后可以加final final ...

随机推荐

  1. H5 拖拽元素

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. The bind() Method

    The bind() method was added in ESMAScript 5, but it is easy to simulate in ESMAScrpt 3. As its name ...

  3. P1011 圆柱体的表面积

    题目描述 输入底面半径 \(r\) 和高 \(h\) ,输出圆柱体的表面积,保留 \(3\) 位小数. 输入格式 输入包含两个实数 \(r,h(1 \le r,h \le 1000)\) 且保证输入的 ...

  4. Springboot上传文件临时目录无效

    一个奇葩问题,虽然解决了,但还是没弄清楚,小记一笔. 年后回来,测试人员对年前的3次迭代的功能进行了回归测试,然后发现所有excel导入的功能都失效了.作为后台开发人员,当然是第一时间打开运行日志排查 ...

  5. C# 已知点和向量,求距离的点

    已知一个点 P 和向量 v ,求在这个点P按照向量 v 运行距离 d 的点 B . 已经知道了一个点 P 和他运动方向 v ,就可以通过这个求出距离点 P 为 d 的点 B. 首先把 v 规范化,规范 ...

  6. 2018-2-13-win10-uwp-csdn-博客阅读器

    title author date CreateTime categories win10 uwp csdn 博客阅读器 lindexi 2018-2-13 17:23:3 +0800 2018-2- ...

  7. mysql5.7密码修改与报错分析

    1.修改密码 修改密码: vim /etc/my.cnf 的mysqld字段加入skip-grant-tables 重启MySQL,service mysqld restart 终端输入 mysql ...

  8. 【Linux】nl笔记

    nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等 ...

  9. 看各类框架源码淘来的一些JavaScript技巧

    1. 创建定长的JavaScript数组,并赋空值: 出自VUE文档Render函数讲解 // 创建定长20的JavaScript数组,并把每个项的值设为null Array.apply(null, ...

  10. DEVOPS技术实践_04:Jenkins参数化构建

    一.参数化构建 1.1 各个参数的信息 凭据参数存储一个用户的账号密码信息,等等,运用最多的是选项参数 1.2 使用选项参数 构建已经变成参数化构建 1.3 获取这个值,修改Jenkinsfile文件 ...