这里写目录标题
- 一、对象与对象引用的区别是什么?
- 二、对象作为参数传递的特点是什么?
- 三、对象初始化顺序是怎样的?
- 四、类的static字段与非static字段的区别是什么?什么情况应该使用static修饰符?
- 五、Java中final修饰符都有什么作用?
- 六、Java中float[10] arr; 语句正确么?
- 七、Java数组元素类型为基本数据类型和引用类型时,有什么不同?
一、对象与对象引用的区别是什么?
通俗简单地认为,Java的内存分为堆内存和栈内存(堆在应用程序生命周期内一直存在,而栈在方法调用完毕后就释放)。类和对象被分配到堆中,对象引用和方法执行时用的局部变量和形式参数则放到栈空间当中。
以类A为例:
A p;//对象声明(p为对象引用)
p = new A();
注:
1. 只有类中没有被static修饰的属性被复制到对象中(方法不被复制过去)。
2. 对象可以通过 “对象引用.方法名” 调用对应类中的方法,调用时系统会在栈中为其开辟用于储存其局部变量的和形式参数的空间,调用完后再释放空间。
(static说明见下)
二、对象作为参数传递的特点是什么?
对象是引用传递,传递的是对象的地址,对象只有一个。如下面两个例子:
例一:
package hello;
class IntClass1{
int value;
}
public class RunIntClass1 {
public static void modifyValue(IntClass1 s,int val) {
s.value=val;
}
public static void main(String[] args) {
IntClass1 a = new IntClass1();
modifyValue(a,8);
System.out.println(a.value);
}
}
将实参对象引用a中的对象的地址复制到形参对象引用s中,s和a指向同一个对象。
例二:
package hello;
class IntClass2{
int value;
}
public class RunIntClass2 {
public static IntClass2 getInstance() {
//在方法中产生对象
IntClass2 s = new IntClass2();
s.value = 8;
return s;
}
public static void main(String[] args) {
IntClass2 a;
a = getInstance();
System.out.println(a.value);
}
}
在方法getInstance()中产生的对象引用s所指向的对象没有在方法执行完后自动释放空间(和c/c++不同),其地址作为返回值赋给对象引用a。
三、对象初始化顺序是怎样的?
1.系统会对数据成员进行默认初始化。
2.执行数据成员定义处的初始化语句。
3.调用构造方法为数据成员指定初值。
package hello;
class IntClass{
int value;//自动初始化,默认值为0
//int value=5; //在定义时指定初值
public IntClass() {}
//定义构造方法将属性value初始化
public IntClass(int val) {
value=val;
}
}
public class IntClassConstructor {
public static IntClass getInstance() {
//调用构造方法从而省略了s.value代码
IntClass s=new IntClass(8);
//s.value=8;
return s;
}
public static void main(String[] args) {
IntClass a=new IntClass();
System.out.println(a.value);
a=getInstance();
System.out.println(a.value);
}
}
四、类的static字段与非static字段的区别是什么?什么情况应该使用static修饰符?
1.static字段:
(1).修饰数据成员:用static修饰符修饰的数据成员是不属于任何一个类的具体对象,而是属于类的静态数据成员;它被保存在类的内存区的公共存储单元中,而不是保存在某个对象的内存区中,因此,一个类的任何对象访问它时,存取到的都是相同的数值;访问方式为通过类名加点操作符来访问,也可通过对象引用来访问。《Java开发手册》强制使用类名(而不是该类的对象引用)访问静态方法和静态变量。
例 static数据成员初始化:
class IntClass{
static int num=0;//静态数据成员初始化
int value=5; //在定义时指定初值
public IntClass() {}
//定义构造方法将属性value初始化
public IntClass(int val) {
value=val;
}
}
public class IntClassConstructor {
public static IntClass getInstance() {
IntClass s=new IntClass(8);
return s;
}
public static void main(String[] args) {
IntClass a=new IntClass();//value被初始化为5
System.out.println(a.value);
IntClass.num++;//静态数据成员自加
a=getInstance();
a.num++;//静态数据成员自加
System.out.println(a.num);
}
}
这两行有警告(通过对象引用来访问):
结果:
静态数据成员仅在类加载时进行初始化,且只执行一次初始化。
(2).static方法:static方法是类方法,但可以被所有对象所访问,引用这个方法时,可以使用对象名做前缀,也可以使用类名做前缀。《Java开发手册》强制使用类名(而不是该类的对象引用)访问静态方法和静态变量;static方法内部的代码,只能访问类中的static属性或方法,不能直接访问类中的非static属性或方法(因为那是对象方法),但非static方法(对象方法)可以访问static数据成员;main方法是特殊的静态方法,是application程序入口点,必须写成public static void main(String [] args)的形式。
例 static方法:
class IntClass{
static int num=1;//静态数据成员初始化
int value=5; //在定义时指定初值
public IntClass() {}
//定义构造方法将属性value初始化
public IntClass(int val) {
value=val;
}
static int countNum() {
return num;
}//静态方法
}
public class IntClassConstructor {
public static IntClass getInstance() {
IntClass s=new IntClass(8);
return s;
}
public static void main(String[] args) {
System.out.println(IntClass.countNum());
IntClass a=new IntClass();//value被初始化为5
System.out.println(a.value);
IntClass.num++;//静态数据成员自加
a=getInstance();
a.num++;//静态数据成员自加
System.out.println(a.num);
}
}
结果:
当首次访问某类的静态字段或静态方法时,会加载该类(.class),并执行静态初始化语句。
(3).静态代码块:一个类中可以使用不包含在任何方法体中的静态代码块,当类被装载时,静态代码块被执行,且只被执行一次,静态代码块经常用来对类中定义的属性进行初始化。
例:
public class Test2 {
static int value ;
static {
value = 3;
System.out.println("value="+value);
}
public static void main(String[] args){ }
}
结果:
2.非static字段:
(1).数据成员:被复制到对象中,每个对象中都有其各自的属性;通过对象引用访问。
(2).方法:通过对象引用调用,在调用时系统会为方法开辟一个栈空间,用于存放方法中的局部变量和形式参数,并且方法在执行时还能访问复制到对象中的属性,其效果如同方法也被复制的对象中一样。方法执行完毕之后,栈空间被释放。
3.什么时候使用static修饰符:
像一些所有对象都相同的属性,比如类中所有对象的个数。实际编程中灵活运用。
五、Java中final修饰符都有什么作用?
1.final修饰属性,则属性为常量。
例:
final int NUM = 20;
NUM = 30; // 编译错误
2.如果修饰方法,则该方法在子类当中不能被覆盖,可防止任何继承类修改此方法,保证了程序的安全性和正确性。
例:
class Parent {
public final void method1(){}//这个方法不能被子类覆盖
}
class Child extends Parent {
public final void method1(){…}//编译错误
3.final修饰类,则该类不能被继承。
例:
class Parent {
}
final class Person extends Parent{
} //可以继承Parent类
class Child extends Person{
} //编译报错,不能继承Person类
六、Java中float[10] arr; 语句正确么?
不正确;Java语言数组声明时,不可在方括号内指定数组大小因为此时并未分配数组空间,可以使用new给数组分配空间,指定数组长度。
例如:
int[] arr = new int[10]; //此时分配了数组空间,每个单元初始化为默认值0
七、Java数组元素类型为基本数据类型和引用类型时,有什么不同?
1.数组元素为基本数据类型的情形
例如:
int[] arr = new int[10]; //此时分配了数组空间,每个单元初始化为默认值0
产生一个有10个单元,类型为int的数组对象,所有单元的初值为0。
2.数组元素为引用类型
例如:
String[] example = new String[10]; //对象引用数组`
产生一个具有10个单元的数组对象,每个单元存放的是1个String对象的引用,所有单元的初值为null,此时并未创建具体的String对象
for(String x: example)
System.out.println(x); 输出结果为10个null
为数组对象引用赋值后,才能使用数组元素,否则抛出 NullPointerException异常
例如:
example[0] = new String(“ab”); //创建String对象,赋值给example[0],
//此时example的第一个元素指向String对象,从而可以操纵String对象