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

final

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

作用在类上               则为final类,final类不能被继承。一般用于工具类时,同时把工具类构造函数声明为私有,暴露静态共有方法

作用在成员变量上    则视为常量。此时赋值方式有三种:(1)声明时赋值(2)构造函数中赋值(3)代码块中赋值。 即不管哪种方式都要保证在使用该变量之前要确保已经有值。使用该特性,可以强制赋值。final变量因为不可变,所以可以安全的存在于多线程中。

作用在方法上           作用在方法上可以保证该方法不能被重写

作用在参数上           保证在方法体内部参数值不会被再次赋值,一般好的编程习惯应该把参数值视为final,不管有没有显示使用final(重构)

static

static关键字是隶属于类而非对象。这也就意味着不管声明了几个对象,static关键字所修饰的空间只占用一份。改变了之后,所有的引用它的都会发生变化。静态成员变量为所有类的对象共享。不像对象之间的变量是无影响的。所以对于static修饰的成员变量或者静态代码块是在类加载的时候已经装载。这种特性可以做一些初始化的工作而且保证只初始化了一次。

作用在包上 (import static(注意这里不是static import)  com…..ClassName.* 静态导包)这种以后再使用包里面的静态方法或者成员变量时会比较方便。eg:

import static java.lang.Integer.*;
int max_value = MAX_VALUE;
toHexString(max_value);

这样就导入了Integer类下面所有的静态方法和成员变量。在使用的时候就可以省去Integer,直接使用。

作用在类上       修饰类则为静态类。只能作为静态内部类,如果直接修饰类,则不能通过编译。

作用在方法上   修饰方法则为静态方法。静态方法中不能使用非静态变量。因为静态方法中不能确定该方法是否有被初始化。但是非静态方法可以引用静态变量。

作用在变量上   作用在变量上则为静态变量。静态成员变量一般声明为final的。因为隶属于该类所有对象,可更改存在着危险。

代码块

代码块分为普通代码块和构造代码块

普通代码块:在方法或语句中出现的{},用的比较少。执行顺序是按声明顺序执行。eg:

1 public static void main(String[] args) {
2         {
3             System.out.println("普通代码块-先声明");
4         }
5         System.out.println("函数普通");
6         {
7             System.out.println("普通代码块-后声明");
8         }
9     }

程序输出结果如下:

普通代码块-先声明
函数普通
普通代码块-后声明

构造代码块:直接在类中定义且没有static关键字的代码块,比较常用。执行顺序是在构造函数执行之前执行,每声明一个对象都会执行一次。

 1 public class CodeBlock {
 2     {
 3         System.out.println("构造代码块-先声明-执行");
 4     }
 5     public CodeBlock(){
 6         System.out.println("构造器执行");
 7     }
 8     {
 9         System.out.println("构造代码块-后声明-执行");
10     }
11     public void plainFunc(){
12         System.out.println("普通方法执行");
13     }
14     public static void main(String[] args) {
15         System.out.println("main方法");
16         CodeBlock cb1 = new CodeBlock();
17         cb.plainFunc();
18         CodeBlock cb2 = new CodeBlock();
19     }
20 }

程序输出结果如下:

main方法
构造代码块-先声明-执行
构造代码块-后声明-执行
构造器执行
普通方法执行
构造代码块-先声明-执行
构造代码块-后声明-执行
构造器执行

结论:

执行顺序:main方法->构造代码块->构造函数->普通方法
每实例化一个对象,则执行一次构造代码块

静态代码块

在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。

如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。

注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。

 1 class Code{
 2     {
 3       System.out.println("Code的构造块");
 4     }
 5
 6     static{
 7         System.out.println("Code的静态代码块");
 8         }
 9
10     public Code(){
11         System.out.println("Code的构造方法");
12         }
13     }
14 public class CodeBlock{
15      {
16       System.out.println("CodeBlock的构造块");
17      }
18
19      static{
20         System.out.println("CodeBlock的静态代码块");
21         }
22
23         public CodeBlock03(){
24              System.out.println("CodeBlock的构造方法");
25             }
26
27       public static void main(String[] args){
28             System.out.println("CodeBlock的主方法");
29             new Code();
30             new Code();
31             new CodeBlock();
32             new CodeBlock();
33           }
34     }

程序输出如下

CodeBlock的静态代码块
CodeBlock的主方法 //这里还没有加载Code,所以先执行主方法,再执行Code的静态代码块
Code的静态代码块
Code的构造块
Code的构造方法
Code的构造块
Code的构造方法
CodeBlock的构造块
CodeBlock的构造方法

内部类

⒈成员内部类⒉静态内部类⒊局部内部类⒋匿名内部类

定义

将一个类的定义放在另一个类的定义内部,这就是内部类

初见内部类

内部类的创建就和定义的一样,把一个类定义在另一个类的内部(java语法规定一个类中只能有一个是public的,所以内部类不能用public修饰)

 1 public class Parcel2 {
 2   class Contents {
 3     private int i = 11;
 4     public int value() { return i; }
 5   }
 6   class Destination {
 7     private String label;
 8     Destination(String whereTo) {
 9       label = whereTo;
10     }
11     String readLabel() { return label; }
12   }
13   public Destination to(String s) {
14     return new Destination(s);
15   }
16   public Contents contents() {
17     return new Contents();
18   }
19   public void ship(String dest) {
20     Contents c = contents();
21     Destination d = to(dest);
22     System.out.println(d.readLabel());
23   }
24   public static void main(String[] args) {
25     Parcel2 p = new Parcel2();
26     p.ship("Tasmania");
27     Parcel2 q = new Parcel2();
28     // Defining references to inner classes:
29     Parcel2.Contents c = q.contents();
30     Parcel2.Destination d = q.to("Borneo");
31   }
32 }

这里在类Parcel2中创建了两个内部类Contents和Destination。同时每个内部类对应的创建了一个外部类方法,该方法用来返回一个指向内部类对象的引用。这种方式很常用!如果不提供指向内部类对象引用的函数,需要借助“.new”来创建内部类对象(后面会有用法)。如果想从外部类的非静态方法之外的任意位置创建某个内部类对象,那么必须像上述main()方法那样,具体指明这个对象的类型:OutClassName.InnerClassName(eg:Parcel2.Contents),为什么要这么做呢?

注意:非静态内部类对象有着指向外部类对象的引用。

这可以至少解释两个问题:

1、内部类拥有外部类的所有元素的访问权(因为当生成内部类时内部类自动产生了指向外部类对象的引用,该引用可以访问外部类的所有成员)

2、创建内部类对象时,需要指明对象类型,即:

OutClassName out = new OutClassName();

OutClassName.InnerClassName=out.new InnerClassName();

使用 .this 和 .new

如果需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟原点和this。如果需要生成内部类对象,可以使用外部类对象后面紧跟原点和this。

外部类引用:

public class DotThis {
  void f() { System.out.println("DotThis.f()"); }
  public class Inner {
    public DotThis outer() {
      return DotThis.this;
      // A plain "this" would be Inner‘s "this"
    }
  }
  public Inner inner() { return new Inner(); }
  public static void main(String[] args) {
    DotThis dt = new DotThis();
    DotThis.Inner dti = dt.inner();
    dti.outer().f();
  }
}

注意:上面代码DotThis.this返回外部类对象引用,如果直接使用this,则是内部类Inner对象引用,不能通过编译。

创建内部类对象:

public class DotNew {
  public class Inner {}
  public static void main(String[] args) {
    DotNew dn = new DotNew();
    DotNew.Inner dni = dn.new Inner();
  }
}

内部类语法

一、成员内部类(非静态):

1、可以访问外部类所有元素

2、创建对象两种方式:(1)在外部类中声明方法返回内部类对象的引用(2)通过内部类对象后跟原点和new的方式(eg:DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner();)

3、成员内部类中不能包含静态数据(成员变量和方法)

二、静态内部类:

1、不能访问外部类的非静态元素和方法。(因为静态内部类没有指向外部类对象的引用,只能直接通过类名来调用)

2、创建方式比较简单

Outer.Inner inner = new Outer.Inner();
inner.func();

3、可以包含静态数据

三、局部内部类

局部内部类就是可以定义在方法体内,比较少用

四、匿名内部类

interface content{
        int func();
    }
System.out.println(new content(){
            @Override
            public int func() {
                return 1;
            }
        }.func());

内部类优势:

1、可以访问外部类所有元素

2、隐藏性好,只有本类可操作

3、可以解决C++里面的多继承问题。怎么解决?

我们知道,Java不支持多继承(即一个类同时继承两个或多个类),只支持多重继承(即A继承B,B继承C,那么A间接继承了C),利用Java的内部类机制可以做到多重继承的效果。可以声明多个内部类分别继承相应的类,然后对于外部类来说,就同时拥有了相应内部类的功能。

代码执行顺序

1、父类静态代码块->父类静态成员变量初始化->子类静态代码块->子类静态成员变量初始化->(父类代码块->父类成员变量初始化)(这两个谁先声明谁在前面)->子类代码块->子类成员变量初始化->父类构造函数->子类构造函数->...

  • 静态先于非静态执行
  • 代码块可以当做成员变量来看,对于静态代码块,类加载的时候执行;对于非静态代码块,构造函数之前执行,可以想成是在成员变量初始化的时候执行
  • 父类优先于子类执行(因为子类涉及到对父类的重写等操作,只有父类初始完毕了,子类重写和引用才有意义)

参考文章:

1、《java编程思想》

2、http://www.cnblogs.com/sophine/p/3531282.html

时间: 2024-08-05 10:34:16

final、static、代码块、静态代码块、内部类、代码执行顺序的相关文章

2.24 Java基础总结 ①访问权限②static③静态方法④实例初始化块⑤静态初始化块

①访问权限②static③静态方法④实例初始化块⑤静态初始化块一.访问权限 默认是同包protected是有关系的,即同包和不同包的子类private只有本类,public全部   本类   同包 不同包       子类 非子类 子类 非子类 private √         默认(同包) √ √ √     protected √ √ √ √   public √ √ √ √ √ 二.static静态成员变量,类级别,全类共享一个Person.country = "中国":一般用

子父类中码静态代块 构造代码块. 代码块 构造函数 成员变量 实例变量 执行顺序

刚开始接触时,很不容易分清楚 创建子类或者多态的情况: /* 创建子类的情况: 1.父类静态代码块 2.子类静态代码块 3.父类构造块 /实例变量(new 创建的变量成员)//谁在前执行谁,执行完再执行构造函数 4.父类构造函数//父类构造函数有方法,如果方法子类有就执行子类的方法,没有才再执行父类方法.//如果子类有父类没有会报错!//父类私有该方法就执行父类的方法 5.子类构造块/实例变量//谁在前执行谁,执行完再执行构造函数 6.子类构造函数 7.子类普通方法//调用成员变量,看子类的值,

Java 中的 static 使用之静态初始化块

Java 中可以通过初始化块进行数据赋值.如: 在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块.如果使用 static 修饰初始化块,就称为静态初始化块. 需要特别注意:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量. 而普通初始化块只要有创建一个实例(即new一次),就执行一次. 我们来看一段代码: 运行结果: 通过输出结果,我们可以看到,程序运行时静态初始化块最先被执行,然后执行普通初始化块,最后才执行

static使用之静态初始化块

public static HelloWorld { string name; { name = "爱慕课"; } } 需要特别注意:静态初始化块只能在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量. 程序运行时,静态初始化块首先被执行,然后执行普通初始化块,最后执行构造方法.

java面向对象,final,super ,抽象类,重写,代码块,static,this,构造方法,堆栈

在jvm内存中主要分布有以下三个区域: 栈:存放基础数据和自定义对象的引用 堆:主要存储创建的对象,即new出来的对象 方法区:加载存放class文件(字节码文件) 什么是封装? 封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. 封装的优点: 隐藏代码的实现细节,提高安全性. private 私有属性:(调用属性先执行提供的get或set方法) 私有属性: class Person { //姓名 private String name; //年龄 private int age; //

java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构 Cat继承Animal Runner里包含main函数,程序入口 Sing类主要用来打印执行顺序的序列号 二.代码 public class Animal { Sing s1=new Sing(1,"animal\tnot static field"); static Sing s2=new Sing(2,&q

static之静态初始化块

static之静态初始化块 所有的静态初始化块都优先执行,其次才是非静态的初始化块和构造函数,它们的执行顺序是:    父类的静态初始化块    子类的静态初始化块    父类的初始化块    父类的构造函数    子类的初始化块    子类的构造函数      也就是说程序运行时静态初始化块最先被执行,然后执行普通初始化块,最后才执行构造方法.由于静态初始化块只在类加载时执行一次,所以当再次创建对象 hello2 时并未执行静态初始化块. 比如下面的代码: 运行结果: 需要特别注意:1)静态初

初始化代码块和构造器的执行顺序

1 package Lab5; 2 3 4 class Root{ 5 static{ 6 System.out.println("Root的静态初始化"); 7 } 8 { 9 System.out.println("Root普通初始化代码"); 10 } 11 public Root(){ 12 System.out.println("root 无参数构造方法"); 13 }; 14 } 15 16 class Mid extends Roo

Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究

随笔- 40  文章- 0  评论- 1 Java的初始化块.静态初始化块.构造函数的执行顺序及用途探究 Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念.下面探究一下它的执行顺序与可能的用途. 执行顺序 首先定义A, B, C三个类用作测试,其中B继承了A,C又继承了B,并分别给它们加上静态初始化块.非静态初始化块和构造函数,里面都是一句简单的输出. 主类Main里面也如法炮制. 1 class A { 2 st

java中初始化块、静态初始化块和构造方法

(所谓的初始化方法init()是另一回事, 在构造方法之后执行, 注意不要混淆) 在Java中,有两种初始化块:静态初始化块和非静态初始化块.它们都是定义在类中,用大括号{}括起来,静态代码块在大括号外还要加上static关键字. 非静态初始化块(构造代码块):作用:给对象进行初始化.对象一建立就运行,且优先于构造函数的运行.与构造函数的区别:非静态初始化块给所有对象进行统一初始化,构造函数只给对应对象初始化.应用:将所有构造函数共性的东西定义在构造代码块中. 静态初始化块:作用:给类进行初始化