上面我们创建出来了一个Car这个对象,其实在使用new关键字创建一个对象的时候,其实是调用了这个对象无参数的构造方法进行的初始化,也就是如下这段代码
class Car{ public Car(){}
这个无参数的构造函数可以隐藏,由JVM自动添加。也就是说,构造函数能够确保类的初始化。
Java 会尽量保证每个变量在使用前都会获得初始化,初始化涉及两种初始化。
一种是编译器默认指定的字段初始化,基本数据类型的初始化
一种是其他对象类型的初始化,String 也是一种对象,对象的初始值都为null ,其中也包括基本类型的包装类
一种是指定数值的初始化,例如
int a = 11
也就是说,指定a的初始化值不是0,而是11。其他基本类型和对象类型也是一样的。
可以利用构造器来对某些方法和某些动作进行初始化,确定初始值,例如
public class Counter{ int i; public Counter(){ i = 11; } }
利用构造函数,能够把i的值初始化为11。
首先先来看一下有哪些需要探讨的初始化顺序
public class Lifecycle { //静态属性 private static String staticField = getStaticField(); //静态方法块 static { System. out.println(staticField); System. out.println("静态方法块初始化"); } //普通属性 private String field = getField(); //普通方法块 { System. out.println(field); } //构造函数 public Lifecycle() { System. out .println("构造函数初始化"); } public static string getStaticField() { String statiFiled = "Static Field Initial"; return statiFiled; } public static String getField() { String filed = "Field Initial"; return filed; } //主函数 public static void main(String[] argc) { new Lifecycle(); } }
这段代码的执行结果就反应了它的初始化顺序
静态属性初始化静态方法块初始化普通属性初始化普通方法块初始化构造函数初始化
数组是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。数组是通过方括号下标操作符 [ ] 来定义使用。
—般数组是这么定义的
int[] a1; //或者 int a1[];
两种格式的含义是一样的。
可变参数列表
Java中一种数组冷门的用法就是可变参数,可变参数的定义如下
public int add(int. . . numbers){ int sum = 0; for(int num : numbers){ sum += num; } return sum ; }
然后,你可以使用下面这几种方式进行可变参数的调用
add(); //不传参数 add(1); //传递一个参数 add(2,1);//传递多个参数 add(new Integer[] {1,3,2});//传递数组
虽然Java 语言是基于C++的,但是它和C/C++一个重要的特征就是不需要手动管理对象的销毁工作。在著名的一书《深入理解 Java 虚拟机》中提到一个观点
在Java中,我们不再需要手动管理对象的销毁,它是由Java虚拟机进行管理和销毁的。虽然我们不需要手动管理对象,但是你需要知道对象作用域这个概念。
J多数语言都有作用域(scope)这个概念。作用域决定了其内部定义的变量名的可见性和生命周期。在C、C++和Java 中,作用域通常由 { } 的位置来决定,例如
{ int a = 11; { int b = 12; } }
a变量会在两个 { } 作用域内有效,而b变量的值只能在它自己的 { } 内有效。
虽然存在作用域,但是不允许这样写
{ int x = 11; { int x = 12; } }
这种写法在C/C++中是可以的,但是在Java中不允许这样写,因为Java设计者认为这样写会导致程序混乱。
this和super都是Java 中的关键字
this 表示的当前对象,this 可以调用方法、调用属性和指向对象本身。this 在Java 中的使用一般有三种:指向当前对象
public class Apple { int i = 0; Apple eatApple(){ i++; return this; } public static void main(String[] args) { Apple apple = new Apple(); apple.eatApple().eatApple(); } }
这段代码比较精妙,精妙在哪呢,我一个eatApple()方法竟然可以调用多次,你在后面还可以继续调用,这就很神奇了,为啥呢?其实就是this 在作祟了,我在eatApple方法中加了一个return this的返回值,也就是说哪个对象调用eatApple方法都能返回对象的自身。
this还可以修饰属性,最常见的就是在构造方法中使用this ,如下所示
public class Apple { private int num; public Apple(int num){ this.num = num ; } public static void main(String[] args) { new Apple(10); } }
main方法中传递了一个int值为10的参数,它表示的就是苹果的数量,并把这个数量赋给了num 全局变量。所以num 的值现在就是10。
this 还可以和构造函数—起使用,充当一个全局关键字的效果
public class Apple { private int num; private String color; public Apple(int num){ this(num, "红色"); } public Apple(String color){ this(1,color); } public Apple(int num,String color) { this.num = num; this.color = color; } }
你会发现上面这段代码使用的不是this,而是this(参数)。它相当于调用了其他构造方法,然后传递参数进去。这里注意一点:this() 必须放在构造方法的第一行,否则编译不通过
如果你把 this 理解为指向自身的一个引用,那么super就是指向父类的一个引用。super关键字和this—样,你可以使用super.对象来引用父类的成员,如下
public class Fruit { int num; String color; public void eat(){ System. out.println( "eat Fruit"); } } public class Apple extends Fruit{ @0verride public void eat() { super.num = 10; System.out.println( "eat " + num + " Apple"); } }
你也可以使用**super(参数)**来调用父类的构造函数,这里不再举例子了。
下面为你汇总了 this 关键字和 super 关键字的比较。