`
阿尔萨斯
  • 浏览: 4187344 次
社区版块
存档分类
最新评论

Java4Android类和对象的初始化详解

 
阅读更多

1,成员初始化

Java尽力保证:所有变量在使用前都能够恰当的初始化。

1)方法的局部变量。Java以编译时错误来贯彻这种保证。eg:

void f(){
    int i;
    i++; //Error , i not initialized
}
2)类的数据成员。如果是基本类型,他们都会有一个初始值;如果是对象引用,那么这个引用将会被初始化为null。

指定初始化

如果想为某个变量赋值,该怎么做?

1)直接在定义类成员变量的地方为其赋值(注意,C++里面是不可以的,尽管C++新手们总想这么做)

class Depth{}

public class InitialValues{
    boolean bool = true;
    char ch = 'x';
    int i = 999;
    Depth d = new Depth();
}
2)调用某个方法来提供初始值。

public class MethodInit{
int i = f();
int f(){return 11;}
}
这个函数还可以带参数,但必须是初始化过的参数。

public class MethodInit2{
int i = f();
int j = g(i);
int f(){
    return 11;
}
int g(int n){
   return n*10;
}
}
但下面的写法确实错误的

public class MethodInit3{
// int j = g(i) ; //Illegal forward reference
int i = f();
int f(){return 11;}
int g(int n){return n*10;}
}
显然,上述程序的正确性取决于初始化的顺序。编译器会发出“向前引用”的警告。

上述这种在定义的地方就初始化,简单快捷,这样创造出来的每个对象都会具有相同的值。

2,构造器初始化

在C++里面叫做构造函数,这里我们叫做构造器,都一个东西。上一节讲到的自动初始化是一定会被执行的,而且会在构造器之前执行。

public class Counter{
int i;
Counter(){i = 8;}
}
上述代码,i首先会被置为0,然后变为7.

初始化顺序

在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,他们仍然会在任何方法(包括构造器)被调用之前得到初始化。
class Window{
Window(int marker){print("window("+marker+")");}
}
class House{
window w1 = new Window(1);
House(){
print("house()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f(){print("f()");}
Window w3 = new Window(3);

}
public class OrderOfInitialization{
public static void main(String[] args){
    House h = new House();
   h.f();
}
}

/**Output**/
/*
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()*/

静态数据的初始化

class Bowl{
Bowl(int marker){print("Bowl("+marker+")");}
void f1(int marker){print("f1("+marker+")");}
}

class Table{
static Bowl bowl1 = new Bowl(1);
Table(){
    print("Table()");
    bowl2.f1(1);
}
void f2(int marker){
    print("f2("+marker+")");
}
static Bowl bowl2 = new Bowl(2);
}

class Cupboard{
Bowl bowl3 = new Bowl(3);
static Bowl bowl4 = new Bowl(4);
Cupboard(){
    print("Cupboard()");
    bowl4.f1(2);
}
void f3(int marker){
    print("f3("+marker+")");
}
static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization{
public static void main(String[] args){
print("Creating new Cupboard() in main");
new Cupboard();
print("Creating new Cupboard() in main");
new Cupboard();
table.f2(1);
cupboard.f3(1);
}
static Table table = new Table();
static Cupboard cupboard = new Cupboard();
}
/**output*/
/*
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
*/
请务必细心的看上述代码和结果。最好自己能够运行一遍。
初始化的顺序是先静态对象,后非静态对象。
静态初始化只有在必要的时刻才会进行。如果不创建Table对象,也不引用Table.b1,Table.b2,那么静态的Bowl b1 和b2 永远都不会被创建。下面的步骤我们会解析为什么。

对象创建过程

总结下对象创建的过程。假如有一个名为Dog的类:
1)即使没有显式的使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成是静态方法),或者Dog类的静态方法,静态域首次被访问的时候,Java解释器必须查找路径,以定位Dog.class文件。
2)然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
3)当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4)这块存储空间会被清零。这就自动的将Dog对象中的所有基本类型数据都设置成了默认值,而引用则被设置成了null。(再次强调方法内部的局部变量不会被初始化,如果使用未初始化的局部变量会提示编译错误)。
5)执行所有出现于字段定义处的初始化动作。
6)执行构造器。

显式的静态初始化(静态块)

Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(也叫静态块)。
public class Spoon{
static int i;
static {
    i = 47;
}
}
上述代码和静态初始化动作是一样的,代码仅在必要的时刻仅执行一次。
class Cup{
Cup(int marker){
    print("Cup("+marker+")");
}
void f(int marker){
    print("f("+marker+")");
}
}

class Cups{
static Cup cup1;
static Cup cup2;
static {
    cup1 = new Cup(1);
    cup2 = new Cup(2);
}
Cups(){
    print("Cups()");
}
}

public class ExplicitStatic{
    public static void main(String[] args){
     print("Inside main()");
     Cups.cup1.f(99);//(1)
}
    //static Cups cups1 = new Cups();//(2)
    //static Cups cups2 = new Cups();//(3)
}
/**output*/
/*
Inside main()
Cup(1)
Cup(2)
f(99)
*/
上述代码无论是运行(1)还是把(1)注释了运行(2),Cups的静态初始化都会得到执行。(3)也可以打开看看,无关紧要,因为静态初始化动作只进行一次。

非静态实例初始化

它在静态初始化之后,在构造函数之前,前面我们讲述过这个步骤。我们来看一段代码:
class Mug{
Mug(int marker){
    print("Mug("+marker+")");
}
void f(int marker){
    print("f("+marker+")");
}
}

public class Mugs{
Mug mug1;
Mug mug2;
{
    mug1 = new Mug(1);
    mug2 = new Mug(2);
    printf("mug1 & mug2 initialized");
}
Mugs(){
    print("Mugs()");
}
Mugs(int i){
    print("Mugs(int)");
}
public static void main(String[],args){
    print("Inside main()");
    new Mugs();
    print("new Mugs() completed");
    new Mugs(1);
    print("new Mugs(1) completed");
}
}
/** output*/
/*
Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed
*/

这种语法对于支持“匿名内部类”的初始化是必须的。
累了。今天学习到这里。










分享到:
评论

相关推荐

    java数组初始化详解

    java 数组初始化 详解 doc

    Java入门教程(微学苑)-part1

    1.17 Java类和对象的概念 18 1.18 面向对象编程(Object Oriented Programming, OOP) 19 1.19 Java类库及其组织结构 21 1.20 Java import及Java类的搜索路径 22 1.21 Java类的搜索路径 23 2 Java语法基础 24 2.1 Java...

    疯狂Android讲义源码

     5.1 Intent对象详解 197  5.1.1 使用Intent启动系统组件 197  5.2 Intent的属性及intent-filter  配置 198  5.2.1 Component属性 198  5.2.2 Action、Category属性与  intent-filter配置 200  5.2.3 指定...

    【05-面向对象(下)】

    •成员变量是随类的初始化或对象初始化而初始化的。final修饰的成员变量必须由程序员指定初始值。 •对于类属性而言,要么在静态初始化中初始化,要么在声明该属性时初始化。 •对于实例属性,要么在普通初始化块...

    疯狂Android讲义.part2

    18.3.2 初始化游戏状态数据 606 18.4 加载界面的图片 610 18.5 实现游戏Activity 612 18.6 实现游戏逻辑 618 18.6.1 定义GameService组件接口 618 18.6.2 实现GameService组件 619 18.6.3 获取触碰点的方块 620 18.6...

    疯狂Android讲义.part1

    18.3.2 初始化游戏状态数据 606 18.4 加载界面的图片 610 18.5 实现游戏Activity 612 18.6 实现游戏逻辑 618 18.6.1 定义GameService组件接口 618 18.6.2 实现GameService组件 619 18.6.3 获取触碰点的方块 620 18.6...

    Android中persistent属性用法详解

    前段时间在研究telephony时,一直没有在framework下发现对telephony的初始化(PhoneFactory.Java中的makeDefaultPhones函数)的调用。结果全局搜索之后发现在application PhoneApp(packages/apps/Phone)中调用了。但是...

    Android文件操作

    android文件架构详解 cache : 是缓存临时文件夹,据说是除了T-mobile的OTA更新外,别无用处。...init.rc :一个初始化脚本,用於将/system/modules和/system/xbin挂载为cramfs,避免系统被无意破坏

    Android Kotlin开发实例(Hello World!)及语法详解

    Android Kotlin开发实例及语法详解 前言 Kotlin是一种在 Java虚拟机上执行的静态型别编程语言,它主要是由俄罗斯圣彼得堡的JetBrains开发团队所发展出来的编程语言。该语言有几个优势 1. 简洁 它大大减少你需要写...

    实例详解Android快速开发工具类总结

    一、日志工具类 Log.java public class L { private L() { /* 不可被实例化 */ throw new UnsupportedOperationException(Cannot be instantiated!); } // 是否需要打印bug,可以在application的onCreate函数里面...

    Android-StickerView:支持缩放和拖动的贴纸视图。 通常用于将位图标记到另一个。 例如:pdf

    Android-StickerView 支持缩放和拖动的标签视图。 通常用于将位图标记到另一个。 例如:pdf 用途:可用于pdf签名的操作控件 安装 Gradle ... -- sticker初始化宽高 -- > < attr name = " stv_s

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--应用启动之检查版本更新及初始化 |--延时任务的工具类 |--异常之UncaughtExceptionHandler全局捕获处理 |--异步任务AsyncTask的用法 |--异步任务的自定义 |--快捷方式增删查 |--手势识别器GestureDetector的用法 ...

    Android学习系列教程实例.pdf

    1.3. Android 系统的初始化流程 ........... 15 1.3.1. 启动 BootLoader .................... 15 1.3.2. 加载系统内核 ........................ 15 1.3.3. 启动 Init 进程 ......................... 16 1.3.4. ...

    Android下拉列表选项框及指示箭头动画

    初始化状态: 点击弹出下拉选择选项框: 选中后: 注意那个指示箭头,如果把这个控件写的比较精细的话,在下拉-选择-复位过程中箭头是应该有动画旋转效果的。 这种样式的选择框实现方案很多,并且常见、常用,我...

    解析Android中Animation动画的编写要点

    在API Demo的View->Animation下可以找到四个Animation的...初始化Animation,从类的名字可以看出是一个变换View的位置的动画,参数起点横坐标,终点横坐标,起点纵坐标,终点纵坐标。 Animation a = new TranslateAn

Global site tag (gtag.js) - Google Analytics