对象以类为模板产生,内存空间在堆中。在对象引用之前需要先进行声明,当声明被赋予对象之后才能称为对象引用,对象引用的内存空间在栈中。对象引用就好比对象的名片,也可以把对象和对象引用的关系比作电视机和遥控器的关系,对象引用就类似于C语言中的指针。
class Student{ String name; int age; } public class RunStudent{ public static void main(String[] args){ Student A;//对象声明,内存空间在栈中 A = new Student;//给对象声明赋予对象,对象声明变为对象引用,对象的内存空间在堆中 //Student A = new Student;(声明后立即赋予对象)// }对象是引用传递,当对象作为参数传递时,传递的是对象的地址。也就是说,对象只有一个。
class IntClass{ int value; } public class RunIntClass{ public static void modifyValue(IntClass s, int val){ s.value = val;//通过对象引用s进行对象赋值 } public static void main(String[] args){ IntClass a = new IntClass();//产生一个IntClass对象,存放在在堆中,并被a所引用 modifyValue(a,8);//将a的地址传递给s,此时a和s所指的对象是同一个,赋值完毕后s所在的栈空间被释放,s和val消失 System.out.print(a.value);//a仍然引用该对象,通过a操作堆中的对象,显示其属性值 } }1.在没有继承的条件下,实例化一个对象,构造的先后顺序是: 静态成员变量>静态初始化块>成员变量>初始化块>构造方法 一般顺序为:先静态,后非静态;先变量,后初始化块,再是构造方法
public class Test{ public static void main(String[] args){ new A(); } } class A{ B m = new B("成员变量"); static B n = new B("静态成员变量"); { System.out.println("初始化块"); } static{ System.out.println("静态初始化块"); A(){ System.out.println("构造方法"); } } class B{ public B(String str){ System.out.println(str); } }输出结果为: 静态成员变量 静态初始化块 成员变量 初始化块 构造方法
2.在有继承的条件下,,实例化一个对象,构造的先后顺序是: 父类静态成员变量>父类静态初始化块>子类静态成员变量>子类静态初始化块>父类成员变量>父类初始化块>父类构造方法>子类成员变量>子类初始化块>子类构造方法 一般顺序为:先父类,后子类;先静态,后非静态;先变量,后初始化块,再是构造方法
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub new Son(); } } class Parent{ B m = new B("父类成员变量"); static B n = new B("父类静态成员变量"); { System.out.println("父类初始化块"); } { System.out.println("父类初始化块"); } static { System.out.println("父类静态初始化块"); } public Parent() { System.out.println("父类构造方法"); } } class Son extends Parent{ B m = new B("子类成员变量"); static B n = new B("子类静态成员变量"); { System.out.println("子类初始化块"); } { System.out.println("子类初始化块"); } static { System.out.println("子类静态初始化块"); } public Son() { System.out.println("子类构造方法"); } } class B{ public B(String str){ System.out.println(str); } }输出结果为: 父类静态成员变量 父类静态初始化块 子类静态成员变量 子类静态初始化块 父类成员变量 父类初始化块 父类构造方法 子类成员变量 子类初始化块 子类构造方法
用static修饰符修饰的域变量不属于任何一个类的具体对象,而专属于类。其特点为它被保存在类的内存区(堆中)的公共存储单元中,而不是保存在某个对象的内存区中。因此任何一个对象访问它时,存取到的都是相同的数值。访问的方式为“类名.域名”,也可通过对象引用来访问。如用类的静态属性对产生的类对象个数进行统计。
class RunTest { static int num = 0; public RunTest(){ num++; } } public class Test { public static void main(String[] args){ RunTest m1 = new RunTest(); RunTest m2 = new RunTest(); System.out.println(m1.num); System.out.println(m2.num); System.out.println(RunTest.num); } }输出结果为: 2 2 2
以final修饰类属性,则该属性为常量;如果修饰方法,则方法称为最终方法,在子类当中不能被覆盖。利用这一点可以防止子类修改此方法,保证了程序的安全性和正确性。
public Test{ final int num = 0; final void Print(){ System.out.println("此方法不能被子类修改"); } }不正确。正确写法为float[] arr,数组是特殊的对象,该语句为声明浮点型数组对象的固定语句,表明arr是一个浮点型数组的声明,方括号里面不能加参数,声明一个浮点型数组并赋予对象的完整语句为:
float[] arr = new float[10];//产生一个具有10个单元,类型为float的数组对象数组元素类型为基本数据类型时,数组中的元素为基本数据类型;数组元素类型为引用类型时,数组中的元素并不是实实在在的对象,而是对象引用。
MyClass[] a = new MyClass[10];//产生容纳10个MyClass的对象引用的数组,而不是产生10个MyClass对象 int[] b = new int[10];//产生容纳10个整型变量的数组