今天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)
- public class Test{
- public Test(){
- int i;
- i++;
- }
- }
如果改为下面这样就是正确的:
- public class Test{
- //这样i的值是默认的0
- int i;
- public Test(){
- i++;
- }
- }
2、为什么new一个对象就是初始化?
每当用关键字new创建一个对象的时候,java系统会自动调用类的构造器,以保证类的初始化。有时候可以省略构造器,这同时就意味着,调用系统默认构造器。总之,new的时候,总会调用构造器,只不过这个构造器或者是自己写的或者是系统默认构造器。
3、初始化顺序
首先,看一下类中要初始化的内容:静态变量、静态初始化块、变量、初始化块、构造器。
然后,看一个例子来总结他们初始化的顺序:(借助一个F类输出)
- class F{
- public F(String s){
- System.out.println(s);
- }
- }
- public class Test {
- F f = new F("变量");
- static F f1 = new F("静态变量");
- {
- F f2 = new F("变量块");
- F f3 = new F("变量块");
- }
- static{
- F f3 = new F("静态变量块");
- F f4 = new F("静态变量块");
- }
- public Test(){
- F f5 = new F("构造器");
- }
- public static void main(String[] args) {
- new Test();
- }
- }
输出结果为:
静态变量
静态变量块
静态变量块
变量
变量块
变量块
构造器
因此可以总结出,初始化的顺序是:静态变量、静态变量块、变量、变量块、构造器。
最后要注意的一点:前面已经说过,静态变量在内存中只有一个空间,也就是多个对象公用这一个。那么,这里要注意的是,并不是在编译的时候所有静态变量都会初始化,如果没有用到的就不会,直到那次有用到它们才会初始化,还是看例子比较清楚:
- class F{
- public F(String s){
- System.out.println(s);
- }
- }
- //这个类是相对于上一个新加的
- class FF {
- static F f6 = new F("第二次才用");
- }
- public class Test {
- F f = new F("变量");
- static F f1 = new F("静态变量");
- {
- F f2 = new F("变量块");
- F f3 = new F("变量块");
- }
- static{
- F f3 = new F("静态变量块");
- F f4 = new F("静态变量块");
- }
- public Test(){
- F f5 = new F("构造器");
- }
- public static void main(String[] args) {
- new Test();
- //看一下f6什么时候初始化
- new FF();
- }
- }
输出结果为:
静态变量
静态变量块
静态变量块
变量
变量块
变量块
构造器
第二次才用
这说明,并不是类中存在的所有静态方法一开始就被初始化,而是真正用到的时候才进行初始化,而且,静态变量一初始化就不会再有第二次了。
三、重载
含义:方法名相同而参数不同。
1、构造器重载
首先要记录的是,构造器可以重载,例如:
- public class Test {
- public Test(){
- System.out.println("没有参数");
- }
- public Test(String s){
- System.out.println(s);
- }
- public static void main(String[] args) {
- new Test();
- new Test("有参数");
- }
- }
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]; 这句话只是创建了一个引用数组,还要在后面对它进行初始化:
- import java.util.*;
- public class Test {
- public Test(){
- String[] ss =new String[5];
- for(int i=0;i<ss.length;i++){
- ss[i]="nihao"+i;
- }
- //以数组的形式输出
- System.out.print(Arrays.toString(ss));
- }
- public static void main(String[] args) {
- new Test();
- }
- }
输出结果为: [ nihaoo, nihao1, nihao2, nihao3, nihao4 ]
五、可变参数列表
看到了可变参数列表,有点激动,因为它的出现使得写程序灰常容易!
有时候觉得一个方法的参数有点不确定,并且是同一类型的参数不确定,这样的话,我们可以用可变的参数方式来定义这个方法,java系统会根据传入的参数来自己判断。
因为Object是所有类的父类,那么我们就以Object为参数,这样,在调用的时候就可以传入任何参数了,如下:
- public class Test {
- public Test(){}
- public void print(Object... args){
- for (Object obj:args){
- System.out.println(obj+"");
- }
- }
- public static void main(String[] args) {
- Test t = new Test();
- t.print("aa","bb","cc","dd");
- t.print(1,2,3,4);
- }
- }
输出:
aabbccdd
1234
当然,如果是想传入固定类型的,同样可以。
需要注意的一点是:元素的列表和数组之间是可以相互转换的,如下:
- public class Test {
- public Test(){}
- public void print(int... args){
- for (int aa:args){
- System.out.print(aa+"");
- }
- }
- public static void main(String[] args) {
- Test t = new Test();
- int[] a = {1,2,3};
- //传入值是一个数组,同样可以
- t.print(a);
- }
- }
运行结果:123
这说明,数组和可变参数列表之间可以相互转换。
六、总结
感谢很多人,指导我,耐心为我讲解,谢谢你们。
好累……今晚从七点开始整理,一直到现在,但是,收获很多~~~其中代码都运行过了,不掺假的……
内容的大部分都是根据自己的理解写的,不知道哪里有说的不专业的地方,希望大家指出,感谢批评指正……
playplay啦~