Java对象初始化
自动初始化(默认值)
一个类的所有基本数据成员都会得到初始化,运行下面的例子可以查看这些默认值:
class Default{
boolean t;
char c;
byte b;
short s;
int i;
long l;
float f;
double d;
public void show() {
System.out.println("基本类型 初始化值\n"+
"boolean<----->" + t +"\n" +
"char<----->" + c +"\n" +
"byte<----->" + b + "\n" +
"short<----->" + s + "\n" +
"int<----->" + i + "\n" +
"long<----->" + l + "\n" +
"float<----->" + f + "\n" +
"double<----->" + d + "\n"
);
}
}
public class InitValue {
public static void main(String[] args) {
Default d = new Default();
d.show();
}
}
【运行结果】:
基本类型 初始化值
boolean<----->false
char<----->
byte<----->0
short<----->0
int<----->0
long<----->0
float<----->0.0
double<----->0.0
其中,char类型的默认值为空(null)。
对于非基本数据类型而言,对象的句柄也会被初始化:
class Person {
private String name;
// setter
}
class Default {
Person p;
public void show() {
System.out.println("Person<----->" + p);
}
}
public class InitValue {
public static void main(String[] args) {
Default d = new Default();
d.show();
}
}
【运行结果】:
Person<----->null
可见,句柄初始化值为null。这就是说,如果没有为p指定初始化值就调用类似于p.setName的方法,就会出现异常。
规定初始化
如果需要自己为变量赋一个初始值,可以在定义变量的同时赋值。
class Default{
boolean t = true;
char c = 'A';
byte b = 47;
short s = 0xff;
int i = 24;
long l = 999;
float f = 1.2f;
double d = 1.732;
public void show() {
System.out.println(
"boolean<----->" + t +"\n" +
"char<----->" + c +"\n" +
"byte<----->" + b + "\n" +
"short<----->" + s + "\n" +
"int<----->" + i + "\n" +
"long<----->" + l + "\n" +
"float<----->" + f + "\n" +
"double<----->" + d + "\n"
);
}
}
public class InitValue {
public static void main(String[] args) {
Default d = new Default();
d.show();
}
}
甚至可以通过一个方法来进行初始化;
class Person {
int i = set();
//...
}
这些方法也可以使用自变量:
class Person {
int i;
int j = set(i);
//...
}
构建器初始化
构建器进行初始化的优点是可以在运行期决定初始化值。例如:
class Person {
int age;
Person() {
age = 89;
}
}
age首先会初始化为0,然后变成89。对于所有基本类型以及对象的句柄,这种情况都是成立的。
初始化顺序
在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。即使变量定义大量遍布于方法定义的中间,那么变量仍然会在调用任何方法(包括构造函数)之前得到初始化。例如:
class Pet {
Pet(int age) {
System.out.println("Pet(" + age + ")");
}
}
class Person {
Pet t1 = new Pet(1);
Person() {
System.out.println("---Person()---");
t3 = new Pet(33);
}
Pet t2 = new Pet(2);
void show() {
System.out.println("show----running");
}
Pet t3 = new Pet(3);
}
public class OrderOfInitialization {
public static void main(String[] args) {
Person p = new Person();
p.show();
}
}
【运行结果】:
Pet(1)
Pet(2)
Pet(3)
---Person()---
Pet(33)
show----running
上例中,虽然t1、t2、t3的定义遍布于类中,但是初始化的先后顺序是由t1、t2、t3的定义顺序决定的(自己动手调换t1、t2、t3看看结果),且初始化优先于构建器执行,当调用Person的构建器时,t3重新初始化。
静态数据的初始化
如果数据是静态的(static),同样的过程也会执行。若属于基本类型,而且未对其进行初始化,就会自动获得自己的标准基本类型初始值;若它是指向一个对象的句柄,除非创建一个对象同它连接起来,否则得到一个空值(null)。如果在定义时初始化,采取的方式与非静态值是不同的,这是因为static只有一个存储区域。例如:
class Bowl {
Bowl(int marker) {
System.out.println("Bowl(" + marker + ")");
}
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}
class Table {
static Bowl b1 = new Bowl(1);
Table() {
System.out.println("Table()");
b2.f(1);
}
void f2(int marker) {
System.out.println("f2(" + marker + ")");
}
static Bowl b2 = new Bowl(2);
}
class Cupboard {
Bowl b3 = new Bowl(3);
static Bowl b4 = new Bowl(4);
Cupboard() {
System.out.println("Cupboard()");
b4.f(2);
}
void f3 (int marker) {
System.out.println("f3(" + marker + ")");
}
static Bowl b5 = new Bowl(5);
}
public class StaticInitialization {
public static void main(String[] args) {
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table();
static Cupboard t3 = new Cupboard();
}
【运行结果】:
Bowl(1)
Bowl(2)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)
静态代码块
Java允许将其他static初始化工作划分到类内一个特殊的代码块中,这种代码块的形式为static关键字,后面跟着一个方法主体,称为静态代码块。静态代码块只有在第一次生成那个类的对象或首次访问属于那个类的static成员时执行。例如:
class Person {
Person(int age) {
System.out.println("Person(" + age + ")");
}
void f(int age) {
System.out.println("f(" + age + ")");
}
}
class Persons {
static Person p1;
static Person p2;
static {
p1 = new Person(1);
p2 = new Person(2);
}
Persons() {
System.out.println("Persons()");
}
}
public class ExplicitStatic {
public static void main(String[] args) {
System.out.println("Inside main()");
Persons.p1.f(18);//
}
static Persons x = new Persons();//
static Persons y = new Persons();//
}
在标记为1的行内访问static对象p1的时候,或在行1被注释而行2未被注释是,用于Persons的static初始化模块就会运行。若1和2都被注释掉,则用于Persons的静态代码块不会执行。
静态属性和静态代码块执行的先后顺序
class Person {
Person(int age) {
System.out.println("Person("+age+")");
}
}
class Persons {
static Person p = new Person(2); //
static {
p = new Person(3);
}
static Person p = new Person(2); //
}
public class CompStaticInit {
public static void main(String[] args) {
}
static Persons x = new Persons();
}
根据注释1保留2,注释2保留1的结果分析可知,静态属性和静态代码块的执行顺序取决于编码的顺序。谁在前面就先执行谁。
非静态属性的初始化
class Animal {
Animal(int age) {
System.out.println("Animal(" + age + ")");
}
void f(int age) {
System.out.println("f(" + age + ")");
}
}
public class NotStaticInit {
Animal a1;
Animal a2;
{
a1 = new Animal(1);
a2 = new Animal(2);
System.out.println("a1 & a2 initialized");
}
NotStaticInit() {
System.out.println("NotStaticInit");
}
public static void main(String[] args) {
System.out.println("Inside main()");
NotStaticInit x = new NotStaticInit();
}
}
类似于静态代码块,匿名代码块与非静态属性的初始化顺序取决于编码顺序。
继承中的对象初始化过程
class Insect {
int i = 1;
int j;
Insect() {
prt("i = " + i + ", j = " + j);
j = 2;
}
static int x1 = prt("static Insect.x1 initialized");
static int prt(String s) {
System.out.println(s);
return 3;
}
}
public class Beetle extends Insect {
int k = prt("Beeklt.k initialized");
Beetle() {
prt("k = " + k);
prt("j = " + j);
}
static int x2 = prt("static Bootle.x2 initialized");
static int prt(String s) {
System.out.println(s);
return 4;
}
public static void main(String[] args) {
prt("Beetle constructor");
Beetle b = new Beetle();
}
}
【运行结果】:
static Insect.x1 initialized
static Bootle.x2 initialized
Beetle constructor
i = 1, j = 0
Beeklt.k initialized
k = 4
j = 2
对Beetle运行Java时,发生的第一件事情是装载程序到外面找到那个类。在装载过程中,装载程序发现一个基础类,所以随之将其载入。无论是否生成基础类的对象,这一过程都将执行。如果基础类含有另一个基础类,则另一个基础类随即也会载入,以此类推。接下来就在根基础类中执行static初始化,再在下一个衍生类中执行,以此类推。这是因为衍生类的初始化可能要依赖于对基础类成员的初始化。
当类都装载完毕,就能创建对象。首先,这个对象中的所有基本数据类型都会设置成为他们的默认值,对象句柄设为null。然后执行基础类的构建器。这种情况是自动完成的(衍生类的构造函数中默认调用了super(),也可以通过super指定基类的构建器)。基础类构建器完成后,衍生类实例变量就会按本来的顺序得到初始化,然后执行构建器的剩余的主体部分。
总结对象创建的过程:
- 静态只在类加载的时候执行且只执行一次;
- 非静态只有在实例化的时候执行,每次创建对象都执行;
- 静态在非静态之前执行,基类静态优先于衍生类静态执行;
- 静态属性和静态代码块的执行属性取决于它们在类中的位置,谁在前先执行谁;
- 非静态属性和构造块的执行顺序取决于它们在类中的位置,谁在前执行谁。
Java对象初始化的更多相关文章
- Java变量、Java对象初始化顺序
局部变量与成员变量: 局部变量分为: 行参:在方法签名中定义的局部变量,随方法的结束而凋亡. 方法内的局部变量:必须在方法内对其显示初始化,从初始化后开始生效,随方法的结束而凋亡. 代码块内的局部变量 ...
- Java对象初始化详解
在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.本文试图对Java如何执行对象的初始化做一个详细深入地介绍(与对象初始化相同,类在被加载之后也是需要初始化的,本 ...
- Java对象初始化详解(转)
在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.本文试图对Java如何执行对象的初始化做一个详细深入地介绍(与对象初始化相同,类在被加载之后也是需要初始化的,本 ...
- 【转】Java对象初始化详解
来源:MySun 链接:http://mysun.iteye.com/blog/1596959 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.本文试图对Jav ...
- JAVA 对象初始化的过程
对象初始化的过程例:Student S = new Student();1.因为new Student()用到了Student类,所以会把它从硬盘上加载进入内存2.如果有static静态代 ...
- java 对象初始化和代码块初始化顺序
class A { public A(){ System.out.println("测试!!!!!!!!!!!"); } } class Demo19 extends A { { ...
- Java 对象初始化
对象A的创建过程: 1. 构造器实际上是静态方法.当首次创建对象A 或者 A类的静态方法/静态域首次被访问时,Java解释器查找类路径,以定位 A.class文件.(当程序创建第一个对类的 ...
- Java对象初始化顺序
最近我发现了一个有趣的问题,这个问题的答案乍一看下骗过了我的眼睛.看一下这三个类: package com.ds.test; public class Upper { String upperSt ...
- 一文理解java对象初始化顺序
例子 Talk is cheap, Show you the code! public class ParentClass { static int parentStaticField = 1; ...
随机推荐
- AngularJs 解决浏览器在初始化代码未加载完毕时 而出现闪烁的问题
1. ng-cloak; 因浏览器会先加载dom元素 而针对于{{pression}} 由于angularjs 还没加载完,会在页面出现闪烁 2.ng-bind; 用ng-bind代替{{expres ...
- java代理与动态代理的学习
静态代理比较简单,就是代理对象与被代理对象继承相同的接口,代理类负责调用被代理类(委托类)的对象的相关方法去提供具体的服务,一个代理类只能为一个接口服务,要是有很多服务的话需要开很多代理类.而动态代理 ...
- 滚动插件 animatescroll(可以设置要滚动到位置)
1. 引入 <script src="js/animatescroll.js"></script> 2.设置要滚动到的位置 $('目标位置').an ...
- 【Double】double精度问题和int、long除不尽取舍问题
看了老半天,真心没搞懂,留下几篇文章,后面继续跟进吧.... 一.如何理解double精度丢失问题? - 知乎 https://www.zhihu.com/question/42024389/answ ...
- 巨蟒python全栈开发-第10天 函数进阶
一.今日主要内容总览(重点) 1.动态传参(重点) *,** *: 形参:聚合 位置参数*=>元组 关键字**=>字典 实参:打散 列表,字符串,元组=>* 字典=>** 形参 ...
- Windows如何使用Apache的ab工具进行网站性能测试(Apache服务器自带了ab压力测试工具,可以用来测试网站性能,使用简单方便)
打开Apache服务器的安装路径,在bin目录中有一个ab.exe的可执行程序,就是我们要介绍的压力测试工具. 在Windows系统的命令行下,进入ab.exe程序所在目录,执行ab.exe程序.注意 ...
- JS toLowerCase()方法 toUpperCase()方法
toLowerCase()方法: 定义:toLowerCase() 方法用于把字符串转换为小写. 语法:var str = "String"; str .toLowerCase() ...
- query_string查询支持全部的Apache Lucene查询语法 低频词划分依据 模糊查询 Disjunction Max
3.3 基本查询3.3.1词条查询 词条查询是未经分析的,要跟索引文档中的词条完全匹配注意:在输入数据中,title字段含有Crime and Punishment,但我们使用小写开头的crime来搜 ...
- wget -d --header
wget -d --header="Host:www.sina.com" http://202.108.33.84 domain differ ip 防止Wget递归下载 假设Ng ...
- JS给TR隔行换色,鼠标经过有动感
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DT ...