基础------初始化、构造器、重载、数组、可变参数

今天3月14号了,这两天有好多其他的事情影响我,今天才静下心来跑去图书馆看书,加上昨天菜菜的指导,收获不少,今天好好记录一下。同时,很感激小叶,昨天专门打电话,给我上了一下态度课,我确实做得不太好,总是有什么问题就跑去问,问问问,什么时候学会自己解决问题!还有一个,小叶说:小叶学基础,是理解学会的,所以,以后看书要好好理解才对。

今天的内容是编程思想的第五章,初始化与清理。我把自己感觉到不熟悉的整理一下,然后好好记录一下。主要要说的有下面这些吧:

一、类的生命周期和对象的生命周期

1、类的生命周期

对于一个类来说,用javac编译成功后就开始了它的生命周期,整个生命周期是:

加载 ------>验证----->准备----->解析----->初始化---->卸载类 其中,加载就是将.calss文件加载到内存中。我理解的卸载类,是当再次使用javac编译这个类的时候,之前的那个就没有了。(不知道这是不是这个样子,有待考证)

2、对象生命周期

对象是类的实例,一般用new关键字创建一个类的实例,对象的生命周期包括:对象的创建,对象的使用,对象的清除对于对象在内存的创建和结束已经在上一个笔记中有记录,所以,这里就先不说了吧~

二、初始化

1、什么要初始化

首先,java中有两种变量,一种是基本类型变量,像int, char, long, short等八种类型;另一种是非基本类型变量,类,如String, Integer, Long等。

然后说初始化。当一个类别创建的时候,其中包含的各种变量是怎样赋值,java系统有规定。其中,基本类型的变量,因为都存放在栈中,因此在初始化的时候都有各自的默认初始值,而对于一个非基本类型变量来说并不是这样的,非基本类型变量在创建的时候,如String s;这只是创建了一个对象的引用,当使用这个引用的时候系统会报错,因为这个引用不知道它指向哪个对象,因此,这里就要初始化了。

其中一个要说明的一点,非基本类型变量在创建的时候要初始化,也就是要用new,即String s = new String(); 而基本类型变量可以在定义的时候可以不赋值,因为系统可以给它默认值,比如int是0……但是,类的方法中定义的基本类型变量不能不赋值,不赋值的话就会报错,提示没有初始化。例如:(报错说:可能尚未初始化变量i

Code:
  1. publicclassTest{
  2. publicTest(){
  3. inti;
  4. i++;
  5. }
  6. }

如果改为下面这样就是正确的:

Code:
  1. publicclassTest{
  2. //这样i的值是默认的0
  3. inti;
  4. publicTest(){
  5. i++;
  6. }
  7. }

2、为什么new一个对象就是初始化?

每当用关键字new创建一个对象的时候,java系统会自动调用类的构造器,以保证类的初始化。有时候可以省略构造器,这同时就意味着,调用系统默认构造器。总之,new的时候,总会调用构造器,只不过这个构造器或者是自己写的或者是系统默认构造器。

3、初始化顺序

首先,看一下类中要初始化的内容:静态变量、静态初始化块、变量、初始化块、构造器。

然后,看一个例子来总结他们初始化的顺序:(借助一个F类输出)

Code:
  1. classF{
  2. publicF(Strings){
  3. System.out.println(s);
  4. }
  5. }
  6. publicclassTest{
  7. Ff=newF("变量");
  8. staticFf1=newF("静态变量");
  9. {
  10. Ff2=newF("变量块");
  11. Ff3=newF("变量块");
  12. }
  13. static{
  14. Ff3=newF("静态变量块");
  15. Ff4=newF("静态变量块");
  16. }
  17. publicTest(){
  18. Ff5=newF("构造器");
  19. }
  20. publicstaticvoidmain(String[]args){
  21. newTest();
  22. }
  23. }

输出结果为:

静态变量
静态变量块
静态变量块
变量
变量块
变量块
构造器

因此可以总结出,初始化的顺序是:静态变量、静态变量块、变量、变量块、构造器

最后要注意的一点:前面已经说过,静态变量在内存中只有一个空间,也就是多个对象公用这一个。那么,这里要注意的是,并不是在编译的时候所有静态变量都会初始化,如果没有用到的就不会,直到那次有用到它们才会初始化,还是看例子比较清楚:

Code:
  1. classF{
  2. publicF(Strings){
  3. System.out.println(s);
  4. }
  5. }
  6. //这个类是相对于上一个新加的
  7. classFF{
  8. staticFf6=newF("第二次才用");
  9. }
  10. publicclassTest{
  11. Ff=newF("变量");
  12. staticFf1=newF("静态变量");
  13. {
  14. Ff2=newF("变量块");
  15. Ff3=newF("变量块");
  16. }
  17. static{
  18. Ff3=newF("静态变量块");
  19. Ff4=newF("静态变量块");
  20. }
  21. publicTest(){
  22. Ff5=newF("构造器");
  23. }
  24. publicstaticvoidmain(String[]args){
  25. newTest();
  26. //看一下f6什么时候初始化
  27. newFF();
  28. }
  29. }

输出结果为:

静态变量
静态变量块
静态变量块
变量
变量块
变量块
构造器
第二次才用

这说明,并不是类中存在的所有静态方法一开始就被初始化,而是真正用到的时候才进行初始化,而且,静态变量一初始化就不会再有第二次了。

三、重载

含义:方法名相同而参数不同。

1、构造器重载

首先要记录的是,构造器可以重载,例如:

Code:
  1. publicclassTest{
  2. publicTest(){
  3. System.out.println("没有参数");
  4. }
  5. publicTest(Strings){
  6. System.out.println(s);
  7. }
  8. publicstaticvoidmain(String[]args){
  9. newTest();
  10. newTest("有参数");
  11. }
  12. }

2、方法重载

方法重载用到的地方很多,这里就不举例子了。主要说一下,什么样的重载才叫真正的重载?

(1)独一无二的参数列表可以区分

(2)参数的顺序不同也可以区分(但是这种情况不提倡使用)

3、重载中,类型的转换

(1)实际传入参数类型 < 重载方法声明的参数类型,则:提升实际参数类型

(2)实际传入参数类型 > 重载方法声明的参数类型,则:要在调用的时候进行类型转换:f( (int) charvalue )

四、数组初始化

(1)基本类型数组

第一、确定数组中元素个数:int[] a = {1,2,3}

第二、不确定数组元素个数(记得c里面不允许这样):int[] a = new int[变量]

(2)非基本类型数组

String[] ss =new String[5]; 这句话只是创建了一个引用数组,还要在后面对它进行初始化:

Code:
  1. importjava.util.*;
  2. publicclassTest{
  3. publicTest(){
  4. String[]ss=newString[5];
  5. for(inti=0;i<ss.length;i++){
  6. ss[i]="nihao"+i;
  7. }
  8. //以数组的形式输出
  9. System.out.print(Arrays.toString(ss));
  10. }
  11. publicstaticvoidmain(String[]args){
  12. newTest();
  13. }
  14. }

输出结果为: [ nihaoo, nihao1, nihao2, nihao3, nihao4 ]

五、可变参数列表

看到了可变参数列表,有点激动,因为它的出现使得写程序灰常容易!

有时候觉得一个方法的参数有点不确定,并且是同一类型的参数不确定,这样的话,我们可以用可变的参数方式来定义这个方法,java系统会根据传入的参数来自己判断。

因为Object是所有类的父类,那么我们就以Object为参数,这样,在调用的时候就可以传入任何参数了,如下:

Code:
  1. publicclassTest{
  2. publicTest(){}
  3. publicvoidprint(Object...args){
  4. for(Objectobj:args){
  5. System.out.println(obj+"");
  6. }
  7. }
  8. publicstaticvoidmain(String[]args){
  9. Testt=newTest();
  10. t.print("aa","bb","cc","dd");
  11. t.print(1,2,3,4);
  12. }
  13. }

输出:
aabbccdd
1234

当然,如果是想传入固定类型的,同样可以。

需要注意的一点是:元素的列表和数组之间是可以相互转换的,如下:

Code:
  1. publicclassTest{
  2. publicTest(){}
  3. publicvoidprint(int...args){
  4. for(intaa:args){
  5. System.out.print(aa+"");
  6. }
  7. }
  8. publicstaticvoidmain(String[]args){
  9. Testt=newTest();
  10. int[]a={1,2,3};
  11. //传入值是一个数组,同样可以
  12. t.print(a);
  13. }
  14. }

运行结果:123

这说明,数组和可变参数列表之间可以相互转换。

六、总结

感谢很多人,指导我,耐心为我讲解,谢谢你们。

好累……今晚从七点开始整理,一直到现在,但是,收获很多~~~其中代码都运行过了,不掺假的……

内容的大部分都是根据自己的理解写的,不知道哪里有说的不专业的地方,希望大家指出,感谢批评指正……

playplay啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值