类和对象的易错点

  • 总结Java程序设计语言中方法参数的使用情况:

    • 一个方法不能修改一个基本数据类型的参数(即数值型和布尔型,在Java中只有基本类型不是对象)。当参数是传入一个数值或布尔值时,传入的参数和原数据基本类型参数是两份不同的拷贝,互不影响。
    • 一个方法可以改变一个对象参数的状态(如传入一个数组引用改变某一个数组元素值,或传入一个对象,改变其属性值。原因在于:方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。但是注意: 当传入一个字符串对象引用时,由于string是final类型的,所有方法体中的修改相当于新创建了一个字符串对象,而不会改变原字符串变量的值)
    • 一个方法不能让对象参数引用一个新的对象,如示例代码:
    public static void swap(Employee x, Employee y){
    	Employee temp = x;
    	x = y;
    	y = temp;
    }
    
    这个交换方法被swap(a,b)调用时,并不能将a对象和b对象交换,原因在于,方法结束时参数变量x和y被丢弃。原来的变量a和b仍然引用这个方法调用之前所引用的对象。
    
  • 总结调用构造器的具体步骤:
    1)所有数据域被初始化为默认值(0、false或null)。
    2)按照在类声明中出现的次序,依次执行所有域初始化语句和初始化快.(即按声明顺序执行静态块和静态语句)
    3)如果构造器第一行调用了第二个构造器,则执行第二个构造器主体。
    4)执行这个构造器的主体。

  • 总结域与局部变量主要不同点:
    必须明确地初始化方法中的局部变量。但是,如果没有初始化类中的域(即成员变量),将会被初始化为默认值(0、false或null)

    初始化域变量时,需注意 如果在编写一个类时没有编写构造器 ,那么系统就会提供一个无参数构造器。这个构造器将会为所有的实例域设置为默认值。于是,实例域中的数值型数据设置为0、布尔型数据设置为false、所有对象变量将设置为null。
    如果类中提供了至少一个构造器,但是没有提供无参数的构造器,则在构造对象时如果没有提供参数就会被视为不合法。因此,在构造一个类时,最好创建一个无参构造器。
    仅当类没有提供任何构造器的时候,系统才会提供一个默认的构造器。

  • 返回类型不是方法签名的一部分。也就是说,不能有两个名字相同、参数类型也相同却返回不同类型值的方法。

  • 继承类代码实例说明:

public class test {
	public static void main(String[] args) {

		// ****向上转型的注意点****

		// 向上直接转型,声明时的子类可以直接被更为抽象的父类引用
		// 声明为 什么类型,该对象就是什么类型,就算其引用的是子类的对象,该对象也只能调用声明的父类中拥有的方法体。
		// father fat = new son();
		// fat.fa();
		// fat.son(); //The method son() is undefined for the type father

		// ****强转的注意点****

		// 两个来自不同的类的对象,不存在向上转型的情况下,不可以互相强转。
		// 编译可以通过,但是会报运行时异常 java.lang.ClassCastException
		// father fat = new father();
		// son son = (son) fat; // father cannot be cast to son

		// 存在向上转型的情况下:
		// 原本是子类对象,后来向上转型之后,被父类引用后,再被强转为子类是可以的。可以正常运行!
		// father fat = new son();
		// son son = (son) fat;

		// 对于null对象强转,下面示例编译可以通过,但会报运行时空指针异常
		// ((son) null).so(); // java.lang.NullPointerException
	}
}

/*
 * 子类
 */
class son extends father {

	public son() {
		System.out.println("子类默认构造器!");
	}

	public son(int a) {
		System.out.println("子类带参构造器!");
	}

	public void test() {
		System.out.println("子类test方法!");
	}

	public void so() {
		System.out.println("子类独有的so方法!");
	}
}

/*
 * 父类
 */
class father {
	father() {
		System.out.println("父类默认构造器!");
	}

	father(int i) {
		System.out.println("父类带参构造器!");
	}

	void test() {
		System.out.println("父类test方法!");
	}

	void fa() {
		System.out.println("父类独有的fa方法!");
	}
}

  • 类型转换总结:

    • 只能在继承层次内进行类型转换。
    • 在将超类转换成子类之前,应该使用instance of进行检查。
    • 继承层次内的转换如:
    Object obj = new Employee("Harry Hacker",350000);
    Employee e = (Employee) obj;
    
  • 抽象类总结:

    • 为了提高程序的清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象的。
    • 除了抽象方法外,抽象类还可以包含具体数据和具体方法。
    • 类即使不含抽象方法,也可以将类声明为抽象类。
    • 抽象类不能被实例化
    • 需要注意,可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。(就如同可以声明一个父类 引用子类对象一样------向上转型)
隐藏边栏