`

面向对象相关概念 & Java Tips

阅读更多
类:一类对象的模板
对象:类的一个具体实例

面向对象的三个基本特征是:封装、继承、多态。



继承:
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
Java是单继承的。除了Object类外,每个类有且只有一个基类。没有明确(explicit)指定基类的类(定义时没有extends),其基类被隐式地(implicitly)指定为Object类。
所以,如果Father implicitly extends Object,Son extends Father,我们不能说Object是Son的基类。但因为继承是Object为根的树状层级关系,Son类“间接继承”了Object类的members。


多态:
定义
引用
多态(动态绑定/运行时绑定/后期)是指“在执行期间(而非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法”。

多态存在的三个必要条件:
引用
1 要有继承
2 要有重写
3 父类引用指向子类对象
注意多态定义中的方法二字!只有类的方法有多态,类的成员变量不存在多态!如下面的例子:
public class AttributeNoPolymorphism {
	public static void main(String[] args) {
		Animal a = new Cat();
		
		//下俩输出说明成员变量不存在多态
		System.out.println(a.i); //10
		System.out.println(a.si);//100 (Dont access the static fields in this way)
		
		//正确的对成员变量的访问是是通过get方法(子类重写了父类的getI()方法)
		System.out.println(a.getI()); //20,这几个sysout中唯一正确的多态体现
		
		//getSi()方法不是重写(static方法无重写这一说!),所以不存在多态
		System.out.println(a.getSi()); //100 (Dont access the static methods in this way)
	}
}

class Animal {
	int i =10;
	static int si = 100;
	
	public int getI() {
		return i;
	}

	public static int getSi() {
		return si;
	}
}

class Cat extends Animal {
	int i = 20;
	static int si = 200;
	
	public int getI() {
		return i;
	}
	
	public static int getSi() {
		return si;
	}
}




重写与重载
重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
关于重写override:
在子类中可以根据需要对从基类中继承来的方法进行重写。
1 子类中重写方法必须和父类中被重写方法具有一样的方法签名(相同的方法名称、参数列表(参数数量一致,对应位置参数类型完全一样))。
2 子类中重写方法的返回类型必须是父类被重写方法的返回类型或其子类型。
3 The overriding method must NOT throw checked exceptions that are new or broader than those declared by the overridden method. For example, a method that declares a FileNotFoundException cannot be overridden by a method that declares a SQLException, Exception, or any other non-runtime exception unless it's a subclass of FileNotFoundException.
4 重写方法不能使用比被重写方法更严格的访问修饰符;private 方法不能被重写。
引用
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.3
Note that a private method cannot be hidden or overridden in the technical sense of those terms. This means that a subclass can declare a method with the same signature as a private method in one of its superclasses, and there is no requirement that the return type or throws clause of such a method bear any relationship to those of the private method in the superclass.
5 构造方法不能被继承,因此不能重写。
6 子类不能用 静态方法 重写父类的非静态方法(或者这样表述:子类不可以定义这样的静态方法:1 和父类中方法名相同且参数相同;2 父类中的该方法为非静态的),否则会报“the static method cannot hide instance method from ParentClassXXX
7 子类不能用 非静态方法 重写父类的静态方法(或者这样表述:子类不可以定义这样的非静态方法:1 和父类中方法名相同且参数相同;2 父类中的该方法为静态的),否则会报“This instance method cannot override the static method from First     ParentClassXXX
8 你可以在父类和子类中都定义方法名、参数、返回值均相同的静态方法,但严格的说这不是重写!因为重写体现的是父类对象与子类对象间的多态性;而这个所谓“重写静态方法”,并不会体现出多态性,因为静态方法是类级的;调用的是父类对象的静态方法(当然,并不推荐通过类实例去调类的静态方法),执行的就是父类里的;调用的是子类对象的静态方法,执行的就是子类里的!
Why static method can't be overridden in Java ?
http://en.allexperts.com/q/Java-1046/Static-method-override.htm
引用
Static means one per class, not one for each object no matter how many instance of a class might exist.
This means that you can use them without creating an instance of a class.Static methods are implicitly final, because overriding is done based on the type of the object, and static methods are attached to a class, not an object.
A static method in a superclass can be shadowed by another static method in a subclass, as long as the original method was not declared final. However, you can't override a static method with a nonstatic method. In other words, you can't change a static method into an instance method in a subclass.
import java.util.AbstractMap;
import java.util.HashMap;

public class OverrideTest {
	public static void main(String[] args) {
		Son son = new Son(); 
        Father father = son;
        
        son.aMethod(null);
        father.aMethod(null);
	}
}

class Father {
	protected AbstractMap aMethod(AbstractMap param) {
		System.out.println("Father");
		return null;
	}  
}  

class Son extends Father {
	/***
	 * 访问修饰符:子类的重写方法不能比被重写方法更严格。如这里可以是protected和public,但不能是private和无访问修饰符。
	 * 返回类型:子类重写方法的返回类型必须是父类被重写方法的返回类型或其子类型。如这里就是被重写方法返回类型AbstractMap的子类型HashMap
	 * 方法名:重写肯定需要相同
	 * 参数列表:必须严格相同:参数数量一致,对应位置参数类型完全一样!如这里被重写方法的参数为AbstractMap类型,则重写方法的参数也必须是AbstractMap类型!既不能更宽泛(如Object)也不能更严格(如HashMap)
	 * 
	 */
	@Override
    public HashMap aMethod(AbstractMap param) {
        System.out.println("Son");
        return null;
    }    
}  

关于重载Overloade:
http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
http://www.java-samples.com/showtutorial.php?tutorialid=284
方法的重载是指一个类中可以定义有相同的名字,但参数不同的多个方法。
方法的名称及其参数类型构成方法的签名,如下面是calculateAnswer方法的签名:
      calculateAnswer(double, int, double, double)
Java是通过方法的签名来区分方法的,这正是重载的理论基础。这里需要注意的是,方法签名是不包含返回值类型的,所以你不可以在代码中声明方法签名一样,只是返回值不同的两个方法,否则编译报错,因为JVM不知道该去调哪个。当然,返回值类型只是不能用来作为方法重载的评判标准,并不是说重载方法就必须具有相同的返回值类型!如下面的也是重载:
	public String m(String s) {
		return s;
	}
	public double m(int i) {
		return i;
	}
另外需要注意的是,父类方法也是可以重载的。如:
//Object类里的equals()方法:
    public boolean equals(Object obj) {
	return (this == obj);
    }

//在自己写的类里这样写不是对Object equals的重写,而是重载,因为你更改了参数类型
    public boolean equals(String obj) {
    	return true;
    }




接口中的成员变量默认是public static final的,即使这三个修饰符你都不加;因为默认是final的原因,所以必须对其进行显式的赋值(http://wuaner.iteye.com/admin/blogs/994819)。


接口和抽象类都是不能实例化的。
如果一个类里包含至少一个抽象方法,这个类必须声明为抽象类
反之不然:抽象类不一定包含抽象的方法,可以全都是具体的方法。
  • 大小: 4.9 KB
  • 大小: 65.1 KB
  • 大小: 14.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics