<init>与<clinit>的区别

<init>与<clinit>的区别

 

今天在看深入Java虚拟机的class文件结构时,看到了这么一句话,

可能出现在class文件中的两种编译器产生的方法是:实例初始化方法(名为<init>)和类与接口初始化方法(名为<clinit>)。

这两种方法有什么区别呢?

首先:这两个方法一个是虚拟机在装载一个类初始化的时候调用的(clinit)。另一个是在类实例化时调用的(init)

首先说说类的初始化:

在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。一个类变量初始化语句是

变量声明后的等号和表达式:

Java代码 复制代码
  1. class Example {
  2. static int size = 3 * (int) (Math.random() * 5.0);
  3. }
class Example {
       static int size = 3 * (int) (Math.random() * 5.0);
}

静态初始化语句是一个以static开头的语句块:

Java代码 复制代码
  1. class Example{
  2. static int size;
  3. static {
  4. size = 3 * (int) (Math.random() * 5.0);
  5. }
  6. }
class Example{
     static int size;
     static {
           size = 3 * (int) (Math.random() * 5.0);
     }
}

所有的类变量初始化语句和类型的静态初始化语句都被Java编译器收集到了一起,放在一个特殊的方法中。这个方法就是<clinit>

我们在来看看<init>这个方法:

<init>方法是在一个类进行对象实例化时调用的。实例化一个类有四种途径:调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。

Java编译器会为它的每一个类都至少生成一个实例初始化方法。在Class文件中,被称为"<init>"

现在知道了吧, 一个是用于初始化静态的类变量, 一个是初始化实例变量!

 

 

 

 

 

 

 

 

 

 

 

在编译生成class文件时,会自动产生两个方法,一个是类的初始化方法<clinit>, 另一个是实例的初始化方法<init>


<clinit>:在jvm第一次加载class文件时调用,包括静态变量初始化语句和静态块的执行

<init>:在实例创建出来的时候调用,包括调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。


  1. import java.util.*;
  2. class ParentTest {
  3. static int y =2;
  4. int yy = 3;
  5. static {
  6. System.out.println("parentTest y = " + y);
  7. }
  8. {
  9. ++y;
  10. }
  11. ParentTest() {
  12. System.out.println("ParentTest construction y = " + y);
  13. }
  14. }
  15. public class Testextends ParentTest{
  16. /**
  17. * @param args
  18. */
  19. static int x =1;
  20. static String s = "123";
  21. static {
  22. if (s.equals("123"))
  23. s = "345";
  24. if (x == 1) {
  25. x = 2;
  26. }
  27. }
  28. {
  29. System.out.println("<init>");
  30. if (s.equals("345"))
  31. s = "678";
  32. if (x == 2)
  33. x = 3;
  34. ++x;
  35. }
  36. public Test() {
  37. System.out.println(x);
  38. System.out.println(s);
  39. }
  40. public Test(String ss) {
  41. System.out.println(x);
  42. System.out.println(s);
  43. }
  44. public staticvoid main(String[] args) {
  45. // TODO Auto-generated method stub
  46. new Test();
  47. System.out.println();
  48. new Test("sssss");
  49. //Test t = new Test("333");
  50. //System.out.println(t.x);
  51. //System.out.println(Test.s);
  52. }
  53. }
import java.util.*;

class ParentTest {
	static int y = 2;
	int yy = 3;
	
	static {
		
		System.out.println("parentTest y = " + y);
	}
	{
		++y;
	}
	
	ParentTest() {
		System.out.println("ParentTest construction y = " + y);
	}
}

public class Test extends ParentTest{

	/**
	 * @param args
	 */
	static int x = 1;
	static String s = "123";
	
	static {
		if (s.equals("123"))
			s = "345";
		if (x == 1) {
			x = 2;
		}
	}
	
	{
		System.out.println("<init>");
		if (s.equals("345"))
			s = "678";
		if (x == 2)
			x = 3;
		++x;
	}
	
	public Test() {
		System.out.println(x);
		System.out.println(s);
	}
	
	public Test(String ss) {
		System.out.println(x);
		System.out.println(s);
	}
	
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Test();
		System.out.println();
		new Test("sssss");
		//Test t = new Test("333");
		//System.out.println(t.x);
		//System.out.println(Test.s);
	}

}


output:

parentTest y = 2
ParentTest construction y = 3
<init>
4
678


ParentTest construction y = 4
<init>
5
678

 

 

.class public Lcom/a/b/c/a;
.super Ljava/lang/Object;


# static fields
.field public static final e:Landroid/net/Uri;

.field public static final f:Landroid/net/Uri;

.field private static final m:Landroid/net/Uri;

.field private static final n:Landroid/net/Uri;


# instance fields
.field a:Ljava/lang/String;

.field b:Ljava/lang/String;

.field c:I

.field d:I

.field g:Landroid/net/ConnectivityManager;

.field h:Landroid/net/NetworkInfo;

.field i:Lcom/a/b/c/b;

.field private j:Landroid/content/Context;

.field private k:I

.field private l:I

.field private o:Ljava/lang/String;


# direct methods
.method static constructor <clinit>()V
    .locals 1

    const-string v0, "content://telephony/carriers"

    invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;

    move-result-object v0

    sput-object v0, Lcom/a/b/c/a;->m:Landroid/net/Uri;

    const-string v0, "content://telephony/carriers/preferapn"

    invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;

    move-result-object v0

    sput-object v0, Lcom/a/b/c/a;->n:Landroid/net/Uri;

    const-string v0, "content://telephony/carriers/preferapn"

    invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;

    move-result-object v0

    sput-object v0, Lcom/a/b/c/a;->e:Landroid/net/Uri;

    const-string v0, "content://telephony/carriers"

    invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;

    move-result-object v0

    sput-object v0, Lcom/a/b/c/a;->f:Landroid/net/Uri;

    return-void
.end method

.method public constructor <init>(Landroid/content/Context;)V
    .locals 2

    const/4 v1, -0x1

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    const/4 v0, 0x0

    iput v0, p0, Lcom/a/b/c/a;->k:I

    iput v1, p0, Lcom/a/b/c/a;->c:I

    iput v1, p0, Lcom/a/b/c/a;->d:I

    iput v1, p0, Lcom/a/b/c/a;->l:I

    iput-object p1, p0, Lcom/a/b/c/a;->j:Landroid/content/Context;

    invoke-direct {p0}, Lcom/a/b/c/a;->g()Ljava/lang/String;

    move-result-object v0

    iput-object v0, p0, Lcom/a/b/c/a;->a:Ljava/lang/String;

    invoke-direct {p0}, Lcom/a/b/c/a;->h()Ljava/lang/String;

    move-result-object v0

    iput-object v0, p0, Lcom/a/b/c/a;->b:Ljava/lang/String;

    const/4 v0, 0x1

    invoke-direct {p0, v0}, Lcom/a/b/c/a;->a(Z)I

    return-void
.end method

 


package com.a.b.c;

import android.content.*;
import android.database.Cursor;
import android.database.SQLException;
import android.net.*;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.ac.f;
import java.lang.reflect.Method;

// Referenced classes of package com.a.b.c:
//   b, c

public class a
{

 public static final Uri e = Uri.parse("content://telephony/carriers/preferapn");
 public static final Uri f = Uri.parse("content://telephony/carriers");
 private static final Uri m = Uri.parse("content://telephony/carriers");
 private static final Uri n = Uri.parse("content://telephony/carriers/preferapn");
 String a;
 String b;
 int c;
 int d;
 ConnectivityManager g;
 NetworkInfo h;
 b i;
 private Context j;
 private int k;
 private int l;
 private String o;

 public a(Context context)
 {
  k = 0;
  c = -1;
  d = -1;
  l = -1;
  j = context;
  a = g();
  b = h();
  a(true);
 }

 


 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值