黑马程序员——面向对象、内部类、多态

来源:互联网 发布:oracle数据库dump转码 编辑:程序博客网 时间:2024/05/16 12:03
------- android培训、java培训、期待与您交流! ----------


面向对象

理解:
首先面向对象是一种思想,
其次它是相对于面向过程而言的,
面向过程是对过程的具体描述,
面向对象将功能封装进对象,强调具备功能的对象。
面向对象是基于面向过程的。

面向对象的特点:

是一种符合人们思考习惯的思想。
可以将复杂的事物简化。
将程序员从执行者变成了指挥者。
完成需求时:
    先要去找具有所需功能的对象来用。
    如果该对象不存在,那么创建一个具有所需功能的对象。
    这样简化开发并提高复用。

面向对象的开发、设计、特征。
开发过程:其实就是不断的创建对象,使用对象,指挥对象做事。
设计过程:其实就是在管理和维护对象之间的关系。
面向对象的特征:
封装(encapsulation)
继承(inheritance)
抽象(polymorphism)

 类与对象的关系

    使用计算机语言就是不断的在描述现实生活中 的事物。
    java中描述事物通过类的形式体现,类是具体事 物的抽象,概念上的定义。
    对象即是该类事物实实在在存在的个体。

类就是图纸
对象就是根据图纸生产出来的对象。

成员变量和局部变量的区别:

    成员变量:
        成员变量定义在类中,在整个类中都可以被访问。
        成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
        成员变量有默认初始化值。
    局部变量:
        局部变量只定义在局部范围内,比如:函数,语句内等。
        局部变量存在于栈内存中。
        作用范围结束,变量空间会自动释放。

匿名对象

匿名对象是对象的简化形式
匿名对象两种使用情况:
    当对对象方法仅进行一次调用时
    匿名对象可以作为实际参数进行传递。

封装(Encapsulation)

封装:指影藏对象的属性和实现细节,只对外提供公共访问方式。
好处:  将变化隔离
    便于使用
    提高重用性
    提高安全性
封装原则:
    将不需要对外提供的内容都影藏起来。
    把属性都影藏,提供公共方法对其访问。

this关键字
特点:this代表其所在函数所属对象的引用。
换而言之:this代表本类对象的引用。

static(静态)关键字


    static关键字:用于修饰成员(成员变量和成员函数)
被修饰后的成员具备以下特点:
    随着类的加载而加载
    优先于对象存在
    被所有对象所共享
   可以直接被类名调用
使用注意
    静态方法只能访问静态成员
    ☆☆静态方法中不可以写this,super关键字
    主函数是静态的

继承

父类又称为超类。
子类可直接访问父类中非私有的属性(成员变量)和行为(方法)。
心得:如果子类中也定义了一个相同名字的属性,那么访问该子类对象,
            获取该属性的时候,就会像方法重写一样,调用的是子类本身的属性。
            
好处:继承的出现提高了代码的复用性。
            继承的出现让类与类之间产生了关系,提供了多态的前提。

继承的特点:

Java只支持单继承,不支持多继承。
Java支持多层继承(继承体系)
定义继承的时候需要注意:
不要仅为了获取其他类中某功能而去继承。
类之间要有所属的关系(is a)的关系,xx1是xx2的一种。

this代表本类引用

super代表父类引用(一般认为)

刚才看到一个帖子问的是为什么super.getClass()返回的是子类的class对象
我看到一个回答中有句话是super关键字并不能代表一个真正意义上的父类引用。。
我感觉很对...
这正能解释了一个问题  为什么在接口实现类的构造器中可以使用super()来调用接口的 “构造器”(接口是没有构造器的)
interface Demo
{}
class Test implements Demo
{
Test()
{
super();
}
}

函数的覆盖(OverRide)(也叫重写)

规则:
1、签名(返回类型,方法名,参数列表)一致
2、访问范围不能变小。
3、抛出的异常不能更多。
    子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重 写或者复写。
    父类中的私有方法,子类中是无法访问的,当然也是无法覆盖的。
    父类中的构造方法子类也是不能覆盖的,子类构造器首先调用父类的构造器。
    (如果子类构造器不写super(),其实子类构造器的第一行默认有super(),也就是调用的是父类的无参构造器,
    如果想调用父类的有参构造器,就必须手写super(参数))。
    
    在子类中如果仍需使用父类被覆盖的方法,可以通过super.函数名获取。
    覆盖注意事项:
        访问权限不能更低
        静态只能覆盖静态
        心得:如果子类要覆盖父类的方法,但返回类型却不相同,那么编译不通过。
        也就是返回类型必须相同。
        抛出的异常不能更多。

final关键字
    final可以修饰类,方法,变量。
    final修饰的类不可以被继承。
    final修饰的方法不可以被覆盖。
    final修饰的变量是一个常量。只能被赋值一次。

    内部类只能访问被final修饰的局部变量。

原因:生命周期不一样,还有就是内部类先把要调用的局部变量的值复制过来,再使用。



访问控制符:

public          可以被任何类访问。
protected    可在同一包中访问,可在子类中访问(不管子类在不在同一个包中)。     
default        可在同一包中访问。    如果子类没有在同一个包中,不能访问
private        只能够被当前类的方法访问。

多态:(overload、override也是多态)

方法的多态跟对象跟类之间的多态。

Animal a = new Cat();
a.eat();//true子父类都有的方法,向上转型之后还是可以调用的,并且调用的是子类的方法。
Cat c = (Cat) a;
c.catchMouch();//如果想要调用父类没有的子类方法(没有覆盖父类的子类方法),
必须向下转型之后才能调用,当然,向下转型的时候要先判断是否是子类实例a instanceof(Cat);
那能不能调用父类的方法呢??//我猜可以的,因为毕竟子类对象继承了父类对象,如果是public是可以
访问的,但是如果是private修饰的呢?那么会访问不了的,因为是其他类中了,
即使是new的对象也不能在其他类中调用private方法。
//也就是向上转型之后只能访问子类中覆盖过父类的方法,跟父类中没有被覆盖的可以访问到的方法。
子类中的其他方法只有向下转型之后才能调用。

多态自始至终都是子类对象在做着变化。
1.多态的体现
    父类的引用指向了自己的子类对象。
    1.函数上的体现(重载、覆盖)
    2.对象的多态
2.多态的前提
    必须是类与类之间有关系,要么继承,要么实现。
    通常还有一个前提:存在覆盖。
3.多态的好处
    多态的出现大大得提高了程序的扩展性。
4.多态的弊端:
    提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5.多态的应用
6.多态的出现代码中的特点(多态使用的注意事项)
在多态中成员函数的特点:(父类指向子类对象的时候)
编译时期:参阅引用型变量的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
动态绑定,静态绑定。
☆面试题:在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。(因为看的是引用所属的类,看的不是对象,直接看的是类,是哪个类中的静态方法)

自我总结:

多态:

父类引用指向子类对象的时候。
编译的时候:如果父类没有此方法,则编译错误,需要先手动向下转型,再调用子类特有方法。
运行的时候:----|成员变量:无论编译还是运行都看等号左边。
        ----|非静态方法:编译看左边,运行看右边。
        ----|静态方法:看引用类型,即父类型。(因为静态是属于类的)

内部类:

将一个类定义在另一个类的里面,对里面那个类就成为内部类(内置类,嵌套类)
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员,
而外部类要访问内部类中的成员,必须要建立内部类对象。

自我总结:

面向对象之所以能够访问外部类成员变量,是因为内部内持有外部类的引用:外部类对象Outer.this(一般都给省略了)

内部类

内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有。
    之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2.外部类要访问内部类,必须建立内部类对象。

访问格式:
1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
可以直接建立内部类对象。
格式:
    外部类名.内部类名 变量名 = 外部类对象.内部类对象。
2.当内部类在成员位置上,就可以被成员修饰符所修饰。
     比如,private:将内部类在外部类中进行封装。
     static:内部类就具备static的特性。
     当内部类被static修饰后,只能直接访问外部类中的static成员。
     出现了访问局限。
     
     在外部其他类中,如何直接访问静态内部类的非静态成员呢?
    new Outer.Inner().function();
     在外部其他类中,如何直接访问静态内部类的静态成员?
        Outer.Inner.function();

  注意:当内部类中定义了静态成员,该内部类必须是静态的。
    当外部类中的静态方法访问内部类时,有两种方法:
    1.把内部类设为static,也可以用外部类对象.内部类对象.方法。

自我总结:

不管在什么位置想要访问内部类及其属性都要注意

           1.如果内部类是非静态的,需要外部类对象.内部类对象.属性或方法。
       2.如果内部类是静态的,则访问格式:外部类.静态内部类.属性或方法。
       注意:外部类中非静态成员都隐式持有外部类的对象,即Outer.this。
                     静态成员则都隐式持有外部类的类,即Outer。
        如果在外部类内部访问其内部类,如果有隐式持有的则直接写出后面的代码,
        如果像静态访问非静态内部类,其没有持有外部类对象,
            则需要new,即new Outer().new Inner().属性或方法。

当描述事物时,事物的内部还有事物(并且不想暴露在外面,让其他类随意访问),该事物用内部类来描述。
因为内部事物在使用外部事物的内容。

内部类定义在局部的时候

1.不能用static修饰,因为static是用来修饰成员的!
2.可以直接访问外部类中的成员,因为还持有外部类中的引用。
  但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。

总结:为什么局部内部类访问外部类中局部变量的时候需要用final修饰?

因为:
1、内部类不是直接调用方法中的参数,而是通过复制到了自己内部,调用的是自己内部的那个参数,也因为如此,导致内部类修改这个参数的时候只改变了自己的参数,而方法中那个局部变量没有改变,为了保持一致性,使用final。
2、二者的生命周期不一样,为了防止方法结束局部变量销毁,而导致内部类无法访问,使用final。

class Outer
{
    int x = 3;
    void method(final int a)
    {
        final int y = 4;
        class Inner
        {
            void function()
            {
                System.out.println(a);
            }
        }
        new Inner().function();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        // 这里是可以的,因为变量都存放在栈内存中,方法调用一次,里面的变量就清空了。
        out.method(3);
        out.mentod(6);
    }
}

匿名内部类:

1.匿名内部类其实就是内部类的简写格式。
2.定义匿名内部类的前提:
    内部类必须继承一个类或者实现接口。
3.匿名内部类的格式:new 父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
5.匿名内部类中定义的方法最好不要超过3个。


new AbsDemo()
{
    void show()
    {
        System.out.println("x===="+x);
    }
}.show();
这是抽象类AbsDemo()的子类对象。(重写了父类,接口中的show()方法。)
匿名对象对其内部方法只能调用一个并且一次。
如果用多态的形式:父类引用指向子类对象,其引用不能调用子类特有对象。

// Test.funtion():Test类中有一个静态方法function。
// .method():function这个方法运算后的结果是一个对象而且是一个Inter类型的对象。
// 因为只有是Inter类型的对象,才可以调用method方法。
Test.function().method();

new Object();---->Object对象。
new Object(){}--->Object子类对象。



------- android培训、java培训、期待与您交流! ----------

原创粉丝点击