zoukankan      html  css  js  c++  java
  • Thinking in Java第五章学习笔记----初始化与清理

    初始化与清理

      初始化和清理是涉及程序安全的两个问题。Java构造器用于新建对象时的初始化,而垃圾回收器则进行清理。

    构造器

      其名称必须与类名一样,虽然构造器是一种特殊的方法,但是每个方法首字母小写的编码风格并不适合用于构造器。

      构造器是没有返回值的,但是new表达式却返回了对新建对象的引用。

    方法重载

      方法重载是构造器所必须的。每个重载方法都必须独一无二的参数列表。甚至参数顺序的不同,也足以区分两个方法。不过一般不建议这么做,因为这会使代码难以维护。当传入的数据类型小于方法中声明的形式参数类型,实际数据类型就会被提升。但是boolean不能转换,char也比较特殊,提升至int。如果反过来,传入大于声明,则必须进行强转,否则报错。(注意,根据返回值的不同来区分方法是不成立的。)

    各参数类型大小顺序排列

      boolean:1/8;byte:1;char:2(一个字符可以存储一个中文汉字);short:2;int:4;float:4;long:8;double:8。(单位:字节)

    this关键字

      只能在方法内部使用,表示对"调用方法的那个对象"的引用。只有在需要明确指出对当前对象的引用时,才有必要使用this。如果在方法内部使用同一个类中的另一个方法,就不用使用this。return this表示返回当前引用。

      通常写this的时候,都是指"这个对象"或者"那个对象",而且它本身表示对当前对象的引用。在构造器中,如果this添加了参数列表,那么就有了不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。通过下面的代码示例将会理解的更加深刻。

    public class Flower {
    	int petalCount = 0;
    	String s = "initial value";
    	Flower(int petals){
    		petalCount = petals;
    		System.out.println("Constructor w/ int arg only,petalCount=" + petalCount);
    	}
    	Flower(String ss){
    		System.out.println("Constructor w/ String arg only,s=" + ss);
    		s = ss;
    	}
    	Flower(String s,int petals){
    		this(petals);
             //this(s)//错误,不能在一个构造器里面调用两次构造器 this.s = s;//因为成员名字和参数S的名称一致,所有采用这种写法加以区分。 System.out.println("String & int args"); } Flower(){ this("hi",47); System.out.println("default constructor(no args)"); } void printPetalCount(){
             //this(11);//错误,不能在非构造器方法里通过this调用构造器。 System.out.println("petalCount =" + petalCount + " s=" + s); } public static void main(String[] args){ Flower x = new Flower(); x.printPetalCount(); } }

    output:

    Constructor w/ int arg only,petalCount=47
    String & int args
    default constructor(no args)
    petalCount =47 s=hi

     关于static的补充

      static方法不能包含this,即不能调用非静态方法。反过来倒是可以。而且在没有创建对象的时候,单依靠对象本身就可以对static方法进行调用。这实际上是static的主要作用。这很像全局方法,Java中禁止使用全局方法,但你在类中置入static方法,就可以访问其他的static方法和static域。

      有些人认为static方法不是"面向对象"的,因为他们的确具有全局函数的含义,使用static方法时,由于并不是通过this来向对象发送信息。的确,要是代码中存在大量的static,就应该重新考虑自己的设计。然而static的概念有其实用之处,许多时候都要用到它,至于是不是面向对象,不是我们说了算的。

    ******************************关于终结处理和垃圾回收,将在后面的博文中详细介绍。******************************

    初始化

      Java尽力保证:所有变量在使用前必须得到恰当的初始化。

      对于类中基本成员(即字段)是基本类型的,会自动为这些成员初始化。但是方法中的局部变量则不会,必须强制程序员赋予初始值,否则编译报错。

    成员初始化的三种情况

      (1)类中基本成员变量:直接在定义的地方为其赋值。(C++中不可以)

      (2)非基本类型的对象:

    class Depth{}
    
    public class Measurement {
    	Depth d = new Depth();
    }

       (3)通过调用某个方法来提供初值,这个方法也可以带有参数,但是这些参数必须是已被初始化了的:

    public calss MethodInit2{
    	int i = f();
    	int j = g(i);
    	int f(){
    		return 11;
    	}
    	int g(int n){
    		return n * 10;
    	}
    }

    构造器初始化

      (1)初始化顺序(牢记):在类的内部,变量定义的顺序决定了初始化的顺序,即使变量定义或者创建对象引用散布于各方法之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

      (2)静态数据的初始化:static关键字不能作用于局部变量,只能作用于域,即成员变量或者对象引用。如果一个域是静态的基本类型域,且没有对它进行初始化,那么它将获得基本类型的标准值,如果它是一个对象引用,那么初始值为null。初始化的查询是先静态对象,再非静态对象。

    class Bowl {
        Bowl(int marker) {
            System.out.println("Bowl(" + marker + " )");
        }
        void f1(int marker) {
            System.out.println("f1(" + marker + ")");
        }
    }
    class Table {
        static Bowl bow1 = new Bowl(1);
        Table() {
            System.out.println("table()");
            bowl2.f1(1);
        }
        void f2(int marker) {
            System.out.println("f2(" + marker + ")");
        }
        static Bowl bowl2 = new Bowl(2);
    }
    class Cupboard {
        Bowl bowl3 = new Bowl(3);//此处的初始化会在静态对象之后。
        static Bowl bowl4 = new Bowl(4);
        Cupboard() {
            System.out.println("cupboard()");
            bowl4.f1(2);
        }
        void f3(int marker) {
            System.out.println("f3(" + marker + ")");
        }
        static Bowl bowl5 = new Bowl(5);
    }
    public class StaticTest {
        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();//此处虽然创建了Cupboard对象,但是静态bowl4和bowl5不会再次被初始化。
            table.f2(1);//这里如果对象引用不是static型,直接使用table.f2是会报错的。下行类似。
            cupboard.f3(1);
        }
        static Table table = new Table();//只有创建Table对象,而且引用静态域时,静态的bowl1和bowl2才会创建。下行类似。
        static Cupboard cupboard = new Cupboard();//第一次对bowl4和bowl5进行初始化。
    }
    

    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)

     显式的静态初始化

      Java允许将对个静态子句组织成一个特殊的静态块。

    class Spoon{
        static int i;
        static int j;
        static Spoon spoon1;
        static{
            i = 7;
            j = 5;
            spoon1 = new Spoon();
        }
    }

    非静态实例初始化:

      和上面类似,可以集中进行初始化。只不过少了static关键字。

    数组初始化:

    int[] a1 = {1,2,3,4};
    int[] a2;
    a2 = a1;

      改变a2中的值,将会影响a1,因为是将a1的引用赋值给了数组a2,a1和a2是不同名的同一数组。 

  • 相关阅读:
    如何评测软件工程知识技能水平?
    创新产品的需求分析:未来的图书会是什么样子?
    案例分析:设计模式与代码的结构特性
    业务领域建模Domain Modeling
    转载:10 Easy Steps to a Complete Understanding of SQL
    二十六个月Android学习工作总结
    android sdk无法更新问题解决
    android中利用view画出一条竖线
    android-Java SoftReference,WeakReference,Direct Reference简介
    Intellij IDEA开发第一个android应用教程
  • 原文地址:https://www.cnblogs.com/promiseslc/p/8626403.html
Copyright © 2011-2022 走看看