<init>与<clinit>的区别
今天在看深入Java虚拟机的class文件结构时,看到了这么一句话,
可能出现在class文件中的两种编译器产生的方法是:实例初始化方法(名为<init>)和类与接口初始化方法(名为<clinit>)。
这两种方法有什么区别呢?
首先:这两个方法一个是虚拟机在装载一个类初始化的时候调用的(clinit)。另一个是在类实例化时调用的(init)
首先说说类的初始化:
在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。一个类变量初始化语句是
变量声明后的等号和表达式:
- class Example {
- static int size = 3 * (int) (Math.random() * 5.0);
- }
class Example {
static int size = 3 * (int) (Math.random() * 5.0);
}
静态初始化语句是一个以static开头的语句块:
- class Example{
- static int size;
- static {
- size = 3 * (int) (Math.random() * 5.0);
- }
- }
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()方法反序列化。
- 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 Testextends 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 staticvoid 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);
- }
- }
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);
}
在编译生成class文件时,会自动产生两个方法,一个是类的初始化方法<clinit>, 另一个是实例的初始化方法<init>
<clinit>:在jvm第一次加载class文件时调用,包括静态变量初始化语句和静态块的执行
<init>:在实例创建出来的时候调用,包括调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。
- 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 Testextends 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 staticvoid 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);
- }
- }
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);
}