面向对象三个特征:
1、封装性
封装性:指的是隐藏对象的属性和方法,对外提供公共的访问方式。
具体的封装之一:
private 修饰符 它将类的成员属性或者成员方法私有化,
如果要使用类中的属性或者方法,可以再类中提供一些对外的见的方法来操作属性或者方法。
而被private修饰的对外是隐藏的,可以使用对外的方法来使用私有化内容同时提高代码的健壮性。
注意:如果将构造方法的属性和方法定义为私有化,那么该类不能被实例化。因为外界不能访问。
2、继承
继承的前提是子类属于父类。有了继承,java才有了多态。
继承之后父类和子类的变量特点:
变量:在子类的成员属性中除了子类特有的,还加载了父类成员属性,所以在子类中,this调用子类本身的属性,super调用父类的属性;
但是如果出现了this调用父类的属性值时,可以理解为this调用了自己的属性值,因为父类的属性值已经加载进来了。少见!
还可以这样理解:this和super都是类的引用,都是指向子类的对象(多态,父类引用指向子类对象),而此时如果子类中没有父类
的那个属性,这时候,这个对象的引用就会到父类中找,其实还是在子类中找,因为父类的属性值已经加载进来了。
总之,子类有就用自己的,没有用的话用父类的。
方法:同名方法覆盖,其实父类的方法还在内存中,只是没有执行。
子类权限要大于父类的权限;静态方法只能覆盖静态方法。
子类在加载Class的时候会先加载父类的Class,这时候,在方法区中(静态区和非静态区),在非静态区中存放方法,父类的先进来,
在子类的方法中,有一个super对象;
由于父类的成员方法没有被复制到子类空间中,所以子类对象在运行时,必须保证父类的class文件可以访问。
以前提到过的在继承中运行顺序是先父类后子类,应该也与父类的class有关吧,必须先生成class文件。
构造函数:子类的构造方法会自动调用父类的无参数的构造方法,不会调用带参数的构造方法,如果需要就必须使用super。
父类的构造方法必须要执行,默认的子类第一行有super(),原因是子类在建立对象的时候,要查看父类是如何初始化那些子类
可以得到的数据;
附加:其实构造函数是用来对一个类以及变量进行实例化。
构造函数的主要作用 :一是用来实例化该类。 二是让该类实例化的时候执行哪些方法,初始化哪些属性。
单继承的原因是:
多继承会带来安全隐患,假如可以多继承,如果两个父类都有同一方法名,方法体不同,子类在调用这个方法的时候,就会出
现错误。这和现实世界类似,一个人只能有一个爹!干爹是实现接口。
finaly:由于继承打破了java的封装性,所以提供finally修饰符,它修饰的类(不能被继承了)、方法以及属性即使被继承了也不允许改变。
3、多态
静态绑定和动态绑定
方法多态的体现(方法的多种形态):
覆盖和重载都是多态的表现,
重载时,编译器在编译期间就可以确定调用哪一个方法,而覆盖则有可能在运行期间才能确定。
重载:静态绑定,在编译期间,就已经明确所要执行的方法;
覆盖:动态绑定,实质是在运行期间,JVM才知道所要执行的具体方法,依据就是子类的对象引用。在不出现对象的多态时,
也就是子类指向子类对象,父类指向父类对象互不干扰,如果出现的父类引用指向了子类对象的情况就出现了对象的多态;
对象多态的体现:
多是动态绑定。
例如:
class Super{
String greeting(){
return "晚上好";
}
String name(){
return "基类";
}
}
class Sub entends Super{]
String greeting(){
return "你好";
}
String name(){
return "子类";
}
}
class differ{
public static void main(String args[]){
Super s = new Sub();//实质还是Sub s = new Sub()
system.out.println(s.greeting() + "," + s.name());//这里就出现了对象的多态父类的引用指向了子类对象,根据动态绑定来看
JVM要区分执行那个方法依据的是具体的对象,虽然是父类的引用,但是
执行的还是子类的方法。因为根据运行期间父类的方法被子类的覆盖了。
}
}
结果:你好,子类。
静态方法运行时的表现和实例方法不同:
例如:
class Super{
static String greeting(){
return "晚上好";
}
String name(){
return "基类";
}
}
class Sub entends Super{]
static String greeting(){
return "你好";
}
String name(){
return "子类";
}
}
class differ{
public static void main(String args[]){
Super s = new Sub();
system.out.println(s.greeting() + "," + s.name());
}
}
结果:晚上好,子类。
静态的更好理解了:虽然存在覆盖,但是,很不好意思,静态的方法不在堆内存中,方法的调用依据具体引用,虽然覆盖了静态方法 ,但是
引用依然是父类的引用,所以,这里又将静态区里面父类的静态方法调用出来了,如果父类中没有这个静态方法就会挂!
多态存在类型的提升可以向上转型和向下转型,向下转型是将父类的引用转成子类类型,
不能出现将父类的对象强制转化成子类的对象;
**over***