JavaSE-深入面向对象
一、面向对象的三大特征
继承、封装、多态
二、封装
封装把过程和数据包围起来,对数据的访问只能通过已定义的接口。
使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
适当的封装可以让代码更容易理解和维护,也加强了代码的安全性。
包的名字必须是小写的
类的权限(2种):
public(可以被任何代码访问)、默认的(仅可被同包的其他代码访问)
类成员的访问权限(4种):
                   本类        同一个包下(子类和无关类)           不同包下的子类           不同包下的无关类
private          Y			
default          Y                            Y		
protected      Y                            Y                                            Y	
public            Y                            Y                                            Y                                  Y
类方法的访问权限(3种):
public、protected、private
三、继承-extends
继承是单方向的,即派生类可以继承和访问基类中的成员,但基类则无法访问派生类中的成员。
在Java中只允许单一继承方式,即一个派生类只能继承于一个基类,而不能象C++中派生类继承于多个基类的多重继承方式。
子类拥有父类的的属性和方法(private成员由于权限关系因此不能访问)
子类可以拥有自己属性和方法,即子类可以对父类进行扩展
子类可以用自己的方式实现父类的方法
Java中的继承树根节点为Object
所有Java中的类都直接或间接继承自Object
构造方法是子类继承不了的,它只能够被调用,而不能被继承。
当构建子类对象时会优先隐式自动调用父类的无参构造方法,
而且是从父类开始向子类一级一级地完成构建(高-->低),
即:如果C继承自B,而B继承自A,那么构建C的对象时,会先调用A的构造方法,
        然后调用B的构造方法,最后调用C的构造方法,以此类推。
父类构造方法的显式调用--super
如果没有无参的父类构造方法,子类必须要显示的调用父类的构造方法
通过super关键字可以在子类构造方法中显式调用父类的构造方法,该调用必须位于子类构造方法的第一行
方法的覆盖/重写:
要想完成方法覆盖/重写,需要遵从以下几个规则(4个):
发生方法覆盖的两个方法的方法名、参数列表必须完全一致(子类重写父类的方法) ,
方法返回值如果是基本数据类型,则返回值应该保持一致;
          如果返回值是类,则子类覆盖方法的返回值必须是父类方法返回值或其的子类,
子类抛出的异常不能超过父类相应方法抛出的异常(子类异常不能大于父类异常) ,
子类方法的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)。
this指向当前对象,super指向父类对象
子类对象可以赋值给父类对象、抽象类对象。
四、多态
Java中多态性指允许不同类的对象对同一消息做出响应。
即:同一消息可以根据发送对象的不同而采用多种不同的行为方式,
因此,多态的主要作用适用于消除类型之间的耦合关系。
对象向上造型:
EG:人 person = new 男人()
父类(编译期类型)的引用指向子类(运行期类型)的对象
对象向下造型:
进行向下造型的对象的运行期类型必须是子类 或 以子类为根的继承树中的其他类型:
EG(Husband是Person的子类):
//向上造型 Person person = new Husband(); //向下造型 Husband husband = (Husband) person;
静态绑定发生在编译时期,动态绑定发生在运行时。
静态绑定:
类的成员变量(属性)都是静态绑定的(编译时);
也就是说,类中声明的成员变量不能被子类中的同名属性覆盖,
EG:
public class StaticBind { public int i = 100; } class StaticBindSub extends StaticBind { public int i = 10; public static void main(String[] args) { //向上造型 StaticBind staticBind = new StaticBindSub(); StaticBindSub staticBindSub = new StaticBindSub(); //类的成员变量和属性都是静态绑定的 System.out.println(staticBind.i); //100 System.out.println(staticBindSub.i); //10 } }
动态绑定:
除了final(后续详细介绍),static(后续详细介绍),private和构造方法是静态绑定外,
其他的方法全部为动态绑定。
这就意味着方法调用将动态使用运行期类型版本
EG:
public class StaticBind { public int i = 100; void foo () { System.out.println("父类的方法"); } } class StaticBindSub extends StaticBind { public int i = 10; @Override void foo () { System.out.println("子类的方法"); } public static void main(String[] args) { //向上造型 StaticBind staticBind = new StaticBindSub(); StaticBindSub staticBindSub = new StaticBindSub(); //调用的是子类的foo() staticBind.foo(); } }
重载方法中具体调用哪个版本是通过静态绑定在编译期就决定了的;
重写覆盖的方法调用哪个版本是通过动态绑定在运行期决定的。
静态绑定一般针对的是成员变量,动态绑定针对的是方法。
instansof:
运算符instanceof用来判断对象是否属于某个类的实例
如果对象的类型是instanceof后面提供的类或其子类,则返回true,反之返回false
EG :
public class TestInstanceOf { public static void main(String[] args) { Human human = new Human(); Man man = new Man(); human.foo(man); } } class Human{ void foo(Human human){ if (human instanceof Man) { System.out.println("男"); } else { System.out.println("女"); } } } class Man extends Human {} class Women extends Human {}
抽象-abstract:
用abstract修饰的类就是抽象类。抽象类是抽象方法的容器。
抽象类不可以直接实例化,只可以用来继承作为其他类的父类存在
抽象方法必须位于抽象类中,抽象类中可以有非抽象方法,抽象类中可以没有抽象方法
抽象方法同样用abstract说明,抽象方法没有方法体,只有方法签名
构造方法和final、static方法不可以修饰为abstract
final:
如果将某个变量修饰为final,那么该变量就成为常量
 [访问权限] final 数据类型 常量名 = 值;
常量在声明时必须初始化,声明之后不能对其进行二次赋值,
其后任何试图对常量进行赋值的语句都将报错。
如果将某个成员方法修饰为final,则意味着该方法不能被子类覆盖,
这就和抽象方法必须由子类实现的规定互相矛盾,因此,final和abstract不能同时修饰一个方法。
final方法的一般声明格式是:
[访问权限] final 返回值类型 方法名(参数列表) {
    ……
}
如果某个类被修饰为final,则该类无法被继承
Java中有一个最常用的final类:java.lang.String
final类的一般声明格式是:
[访问权限] final class 类名{
    成员列表...
}
static:
static 在变量或方法之前,表明它们是属于类的,称为类方法(静态方法)或类变量(静态变量)。
若无static修饰,则是实例方法和实例变量。
和类的其他成员属性不同,static成员并不存放在对象对应的堆空间中,
通过对JVM的分析发现,其会将static成员存放在方法区中,
每个对象的相应static共享同一段内存
实例变量、静态变量、实例方法、静态方法之间的关系:
可以通过类名访问静态变量,也可以通过类对象访问静态变量,
但是注意:要避免后者,因为会增加编译器的成本。
静态方法、普通方法 均可以访问静态变量;
静态方法不可以访问普通变量(实例变量)。
类的实例化对象可以访问其静态方法;
直接通过类名也可以访问静态方法。
实例方法可以直接调用静态方法;
静态方法不可以直接调用实例方法,但是可以通过类对象调用。
接口-interface:
面向接口编程的意思是指:在面向对象的系统中所有的类 或者 模块之间的交互 是由接口完成的
[访问权限] interface 接口名 {
  公开静态常量列表;
  公开抽象方法列表;
}
在接口中的方法均是抽象的,下表中罗列了接口和抽象类的差异:
                         abstractclass                       interface
属性                     不用限制                   public静态常量(public static final)
构造方法              可有可无                            没有
普通方法              可以有具体方法        必须是public抽象方法
子类                     单一继承                  多重实现(接口继承接口时为多重继承)
成员变量方面,在接口中只存在公开静态常量
(即便没有使用static final修饰,Java也会默认确定其性质)
成员方法方面,在接口中只存在公开抽象方法
(即便没有abstract修饰,Java也会默认其抽象性质)
和抽象类一样,它不能用于实例化对象,只能作为继承树的高层结构被子类实现
在描述类与类的继承关系时extends后面只能跟一个名字,
在描述接口与接口之间的继承关系时,extends后面可以跟一个列表。
使用implements关键字来让类实现一个或多个接口。
JDK1.8之后,接口中还可以有默认的方法-default。
类型层次中任何符合override规则的方法,优先于默认方法。
如果一个类实现一个接口,那么他必须实现接口中的所有方法。
枚举-enum:
[访问权限] enum 枚举名{ 
    枚举值列表 
}
                    
                
                
            
        
浙公网安备 33010602011771号