Thinking In Java----2017.1.7 初始化与清理

重载:

 

1.重载的概念:方法名相同,参数不同(形参不同)

2.涉及基本类型的重载:

基本类型能从一个“较小”的类型自动提升至“较大”的类型,此过程一旦涉及重载,可能造成混淆。

具体:如果传入的实际数据类型小于方法中声明的形式参数类型,那么实际数据类型会自动提升。char型略有不同,如果无法找到恰好接受char型的,那么char型直接提升至int型。

如果实际参数类型稍大,则必须进行类型转换,否则编译器会报错。

 

 

 

 

 

this关键字:

1.)

this关键字的含义:this只能在方法的内部使用,它表示的是”调用这个方法的那个对象的引用 ”

比如说一个对象叫做a,他有个increate方法,里面i++,并且return this

所以a.increate()的返回结果是a对象(因为return this了),此时可以继续调用increate方法,就像a.increate().increate().increate().是可以的.

 

还比如,通过this,可以将自身传递给外部方法。例如

class Apple{
    int ID = 0;
    Apple getPeeled(){
        Peeler p = new Peeler();
        return p.peel(this);
    }
    Apple(){
        ID++;
        System.out.println(ID);
    }

}
class Peeler{
    Apple peel(Apple apple){
        return apple;
    }
}

 

2.)this关键字在构造器中的使用:

如果在构造器中对this附加了参数列表,如this(int),this(double),this(float,String),这将表示对符合此形式的某个构造器的明确调用.

注意事项:this(xxx)这种形式必须放在构造器的第一句,并且只能有1句。Only and First

 

 

 

 

 

 

static方法其实就是没用this关键字的方法,因为this表示与对象相关的一些东西,但是static 表示与对象无关。

 

 

 

 

 

 

finalize() :

1.)由于垃圾回收器只知道释放那些经由”new”分配的内存,所以假如我的对象获得了一块“特殊“的内存区域,那么垃圾回收器不知道如何处理这块特殊的内存区域。为了应对这种情况,JAVA允许在类中定义一个名为finalize()的方法。

2.)上述说的特殊情况:JAVA中一切皆对象,对象都是new出来的,所以这种特殊情况是由于可能采用了C语言中的做法,使用了本地方法。本地方法是在Java中调用非Java代码,例如c和c++.

3.)工作原理:一旦垃圾回收期准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以可以用finalize()做一些重要的清理动作。

 

 

 

 

 

成员初始化

 

1)构造器初始化:变量定义处的初始化会优先于构造器里的初始化

例如A a = new A(1);

  Test(){

          a = new A(2);

}

最后 a = A(2);第一次引用的对象A(1)会被作为垃圾回收。

 

2)静态数据的初始化:

  a.)无论创建多少个对象,静态数据就占一份存储区域;

b.)静态数据未被初始化的时候,是基本数据类型的标准初值和null;

c.)初始化顺序:先静态初始化,然后再其他普通的初始化,最后执行构造器初始化。(总结1点就是先初始化静态对象,再是非静态对象

c.1)该类的静态变量------>该类的静态化初始块-------->普通初始化--------->构造器初始化;

c.2)如果存在父类:总结:对象的初始化顺序:首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。 

 

静态成员变量和静态初始化块级别相同非静态成员变量和非静态初始化块级别相同。

 

 

 

d.)静态字句(静态块):java把多个静态初始化动作组织在一起的块。

static{

  Int i = 1;

}

   关键点:静态初始化块动作的发生时机:

1.当首次生成这个类的一个对象的时候或者首次访问属于那个类的静态数据成员的时候。

2.http://blog.csdn.net/deadpanda/article/details/5307932

   静态初始化块是当类被初始化(关于这部分看今日其他笔记)的时候就发生的动作,并且直到程序结束(如果静态块里有静态变量,那该静态变量就会一直存活到程序结束)。比如一个类用main()方法,一定会加载这个类的class文件,此时静态块就会执行。例子如下:

  public class Test {

            //静态变量

            public static String testStatic = "testStatic";

                    //静态初始化块

            static {

                  System.out.println(testStatic);

                  System.out.println("Proc begin");

                  testStatic = "testProc";

                  System.out.println("Proc end");

            }

             //主方法

            public static void main(String[] args) {

                  System.out.println(testProc);

                  System.out.println("main begin");

                  System.out.println("main end");

            }

       }

        执行main方法输出结果:

       testStatic
       Proc begin
       Proc end
       testProc
       main begin
       main end

也就是说当JVM将要执行main方法的时候,先要将Test.class加载到JVM中,此时就执行了静态初始化块中的程序;然后再执行执行main方法中的程序。

 

一个总结很好的博客:

http://blog.csdn.net/leeyu35/article/details/7755304

1.成员变量分为实例变量和静态变量:

实例变量属于一个具体的实例,只有在类实例化之后才真正存在。

静态变量不需要类实例化就已经存在。

2.实例方法和静态方法实例:

实例方法必须在类化以后通过对象调用。

静态方法可以在类实例化之前就使用。

静态方法可以通过A(类).method() 或者 a.method().

实例方法只能a,method().

方法和变量最大的区别:无论是实例方法还是静态方法,在内存中只有1份,只有在调用的时候才会存在,无论该类多少个实例,共用同一个方法。

静态方法只能访问静态成员(静态变量和静态方法),不允许访问实例成员(实例变量和实例方法)。-------->静态块同理,不能访问实例成员。

 

3.静态代码块

在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:

    static {

          语句序列

     }

  ●     静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。

  ●     静态代码块里面的变量都是局部变量,只在本块内有效。

  ●     静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。

  ●     一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。

  ●     静态代码块只能访问类的静态成员,而不允许访问实例成员。

 

c.)数组初始化:

1.)经典例子:

int[] a1 = {1,2,3,4,5};
int[] a2 ;
a2 = a1;
for(int i=0;i<a2.length;i++){
    a2[i] = a2[i]+1;
}
for(int i=0;i<a1.length;i++){
    System.out.println(a1[i]);
}

System.out: 2

System.out: 3

System.out: 4

System.out: 5

System.out: 6

分析: a2 = a1真正做的只是复制了一个引用,他们是同一个数组{1,2,3,4,5}的别名,其实连接着同一数组对象,因此改变a2也就改变了a1,为了测试,有了如下的例子;

 

A a = new A();
A b ;
b = a;
b.i++;
System.out.println(a.i+"测试");

 

 

我们发现a.i也变了,所以类似a2 = a1这种形式,他们只是名字不同,但是连接着同一个对象。

  即:不同引用连接同一个对象!,其中1个修改,另一个也修改。

 

 

 

2.)引用数组(非基本类型的数组):

 

例子:

Integer array = new Integer[20];此时,它还仅仅是一个引用数组,只是确定了长度而已。

当你创建新的对象并将它赋值给引用的时候,初始化才算完成.

如果忘记生成对象,它就是个空引用而已。

 

 

3.)数组生成的方式:

 

1.静态创建和动态创建(更灵活)。

 

 创建数组的三种方式:其实分为2类,一种是静态的创建,如方式一。一种是动态的创建,只不过根据写法的不同分为方式二和方式三:

[java] view plain copy print?

public static void main(String[] args) {  

    // 1.方式一  声明 分配空间并赋值  

    int[] arr1 = {1,2,3};  

    // 2.方式二 显示初始化  

    int[] arr2;  

    arr2 = new int[]{1,2,3};   

    // 3.方式三 显示初始化()  

    int[] arr3;  

    arr3 = new int[3];  

}  

public static void main(String[] args) {

// 1.方式一  声明 分配空间并赋值

int[] arr1 = {1,2,3};

// 2.方式二 显示初始化

int[] arr2;

arr2 = new int[]{1,2,3};

// 3.方式三 显示初始化()

int[] arr3;

arr3 = new int[3];

}


他们的区别,方式一:在声明的时候直接就已经分配空间,并赋值,方式一是不能写成如下这种形式的。

[java] view plain copy print?

int[] arr1;  

arr1 = {1,2,3};//错误写法 编译不同过  

int[] arr1;

arr1 = {1,2,3};//错误写法 编译不同过

方式二和方式三,声明和内存分配是分开的,如上面的例子,

[java] view plain copy print?

int[] arr2;  和  int[] arr3;  

int[] arr2;  和  int[] arr3;

这一步是在栈空间分配一个引用,存放的是一个引用,null

[java] view plain copy print?

arr2 = new int[]{1,2,3};<span style="font-family: Arial, Helvetica, sans-serif;">arr3 = new int[3];</span>  

arr2 = new int[]{1,2,3};<span style="font-family: Arial, Helvetica, sans-serif;">arr3 = new int[3];</span>

到这一步的时候jvm才开始在内存堆区域分配空间,并赋值,方式二直接赋值 1,2,3  方式三 默认初始化,基本类型是 0  布尔类型是 false 引用类型为null,

注:内存一旦分配不能改变,所有说数组长度固定

 

 

 

 

数组长度固定的原因:

当内存分配好了的时候,是不能改变的,所以说数组长度固定.

 

 

 

4.可变参数列表:

a.)参数列表本身其实是一个数组,当你往参数列表里传数组的时候,编译器会发现你的参数已经是数组了,不需要执行任何转换。其他的元素对变成数组。

b.)参数列表里面也可以不传参数,返回1个长度为0的数组。

c.)可变参数列表可以与自动包装机制和谐共处。

d.)f(float f,Integer... args)和f(Integer... args)

当调用这两个方法的时候,会得到错误信息,因为调用的方法是ambiguous(模糊)的。比如f(1,1)和f(2.0,2),虽然我们明白,但是得不到正确的结果。

所以在重载的时候,要么只有1个重载方法使用参数列表,要么不用参数列表。

 

 

5.枚举类型:

public enum What{

LITTLE,MIDDLE,BIG,MOST;

}

Class Test{

What level;

swich(level){

case LITTLE:

Break;

case:xxxxxxx以下省略

}

}

把enum当成类来使用,它有自己的方法:

What.values()(static values)用来按照声明的顺序,产生数组。

Level.ordinal():表示某个特定enum的声明顺序。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值