第一讲 抽象类

一、抽象类的概述
1、抽象类:当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体,为了保证不出问题,方法声明用abstract修饰。
2、抽象类的特点

A:一个类如果有了抽象方法,那么这个类必须是抽象类。抽象类里边可以没有抽象方法,抽象方法只有声明部分而没有具体的方法体。
B:抽象类是不能够被实例化的。不能够创建对象的。
C:如果一个类继承抽象类,那么,它要么重写抽象类中的所有抽象方法,要么本身也是抽象类。

3、抽象类的成员特点

A:成员变量:子类可以直接继承抽象类中的成员变量。(抽象类中的成员变量可以和以前是一样的)
B:成员方法:抽象类中分为两种方法, * 一种是抽象方法,这种方法在子类中必须要被实现。 * 一种是普通的方法。可以被子类直接继承使用。
C:构造方法:抽象类不能被实例化,那么它有构造方法吗?抽象类是class,那么它就有构造方法。它的构造方法有用吗?有,为了让子类实例化的时候使用。

4、抽象类和一般类的不同?

1、该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体。通过抽象方法来表示。
2、抽象类比一般类多个了抽象函数。就是在类中可以定义抽象方法。抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

5、abstract不能和那几个关键字共同存在?

final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。
private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。
        而抽象方法出现的就是需要被复写。
static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。
        可是抽象方法运行没意义。
抽象类中是否有构造函数?
有,抽象类是一个父类,要给子类提供实例的初始化。

6、实例

/*
假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个
奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方
法进行属性访问。

员工类:name id pay

经理类:继承了员工,并有自己特有的bonus。


*/

abstract  class Employee
{
    private String name;
    private String id;
    private double pay;

    Employee(String name,String id,double pay)
    {
        this.name = name;
        this.id = id;
        this.pay = pay;
    }

    public abstract void work();

}



class Manager extends Employee
{
    private int bonus;
    Manager(String name,String id,double pay,int bonus)
    {
        super(name,id,pay);
        this.bonus = bonus;
    }
    public void work()
    {
        System.out.println("manager work");
    }
}

class Pro extends Employee
{
    Pro(String name,String id,double pay)
    {
        super(name,id,pay);
    }
    public void work()
    {
        System.out.println("pro work");
    }
}




class AbstractDemo 
{
    public static void main(String[] args) 
    {
        Manager Manager=new Manager("11","10",100,200);
        Manager.work();
    }
}

二、模板方法设计模式
1、模板方法设计模式

在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,
那么这时就将不确定的部分暴露出去。由该类的子类去完成。

2、实例实现

需求:获取一段程序运行的时间。
原理:获取程序开始和结束的时间并相减即可。

获取时间:System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题。

这种方式,模版方法设计模式。

实现:
abstract class GetTime
{
    public final void getTime()
    {
        long start = System.currentTimeMillis();

        runcode();

        long end = System.currentTimeMillis();

        System.out.println("毫秒:"+(end-start));
    }
    public abstract void runcode();//不确定的方法进行暴露出去让子类去完成

}


class SubTime extends GetTime
{

    public void runcode()//若子类不是abstract,父类抽象类的方法必须实现
    {

        for(int x=0; x<4000; x++)
        {
            System.out.print(x);
        }
    }
}


class  TemplateDemo
{
    public static void main(String[] args) 
    {
        //GetTime gt = new GetTime();
        SubTime gt = new SubTime();
        gt.getTime();
    }
}

第二讲 接口

一、接口的概述
1、接口:当一个类中所有的方法都是抽象的时候,你没必要定义为抽象类,定义为接口就可以了。
接口的格式:interface {}
2、接口的特点:

A:接口是对外暴露的规则
B:接口是功能的扩展
C:接口降低了程序的耦合性。
内聚(自己实现功能的能力)
高内聚,低耦合。
举例:主板和CPU,USB接口,电源插座。
D:扩展说了下接口的理解
狭义的理解就是java中的接口。
广义的理解就是:任何定义的规范都是接口。

3、接口中成员特点

-A:只有成员变量和成员方法。
-B:成员变量 默认修饰符 public static final
int X = 20;
其实是这样的 public static final int X = 20;
-C:成员方法 默认修饰符 public abstract
void show();
其实是这样的 public abstract void show();
建议:为了便于阅读,自己手动加上修饰符。

4、解决了Java中的单继承问题

A:类与类:只能是单继承。 extends
B:接口与接口:可以是单继承,也可以是多继承。 extends
C:类与接口:可以是单实现,也可以是多实现。 implements

5、接口和抽象类的区别

A:抽象类只能被单继承;接口可以被多实现。
B:
--抽象类中的成员:
成员变量:可以是常量,也可以是变量。
成员方法:可以是抽象的,也可以是非抽象的。
构造方法:虽然不可以创建对象,但是可以给子类实例化用。
--接口中的成员:
成员变量:只能是常量。默认修饰符 public static final
成员方法:只能是抽象的。默认修饰符 public abstract
C:抽象类中定义的是体系结构中的共性的内容。接口中定义的是对象的扩展功能。
D:抽象类被继承表示的是:"is a"的关系。xx是yy中的一种。接口被实现表示的是: "like a"的关系。xx像yy中的一种。

6、实录:student类

A:属性:学号,姓名,年龄
B:方法:学习(study),吃饭(抽象eat),抽烟(是不是所有的学员都抽烟呢?),篮球(是不是所有的人都会打篮球呢?)
分析:学员都具备学习的行为和吃饭的行为,但是并不是所有的学员都抽烟,也不是所有的学员都打篮球
 interface Smoking {
    public abstract void smoking();
 }
 interface Sport{
    public abstract void playBasketBall();
 }
描述的是即会抽烟又会打篮球的学生:SmokeStudent extends Student implements Smoking,Sport

一个类只能继承一个类,但是可以实现多个接口,每实现一个接口,功能就扩展了一部分
class wangwu extends Sport implements Study,Sport
{
}

SmokeStudent ss = new SmokeStudent();
ss.eat();
ss.study();
ss.smoking();
ss.playBasketBall();

第三讲 内部类

一,内部类
1、内部类概述

将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
        当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。如定义一个描述人的类,而手、心脏等都属于人,然它们又有自己的功能描述,这时可以在人这个描述类中,定义一个描述心脏的类,也就是内部类。
        编译时,如果代码中有内部类,生成的class文件中会含有这样的文件:Test$1.class。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件。这是内部类的一种编译现象。

2、内部类的访问规则

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

3、访问格式

1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。
        格式:
                 外部类名.内部类名  变量名 =外部类对象.内部类对象;
        如:    Outer.Inner in =new Outer().new Inner();
当内部类在外部类中的成员位置上时,可以被成员修饰符所修饰。比如:
        private:将内部类在外部类中进行封装。 
        static:内部类就局部static的特性。但是当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,直接访问static内部类的非静态成员的格式为:
        new 外部类名.内部类名().方法名();
        如:new  Outer.Inner().function();
在外部其他类中,直接访问static内部类的静态成员格式为:
        外部类名.内部类名.方法名();
        如:Outer.Inner.function();
注意:
        1)当内部类中定义了静态成员时,该内部类必须是static的。
        2)当外部类中的静态方法访问内部类时,内部类也必须是static的。
        3)在实际应用中,内部类通常被定义为private,而很少定义为public。
2、内部类定义在局部
        内部类定义在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部类。
        1)不可以被成员修饰符修饰。如public、private、static等修饰符修饰。它的作用域被限定在了声明这个局部类的代码块中
        2)可以直接访问外部类中的成员,因为还持有外部类中的引用。
注意:内部类不可以访问它所在的局部中非最终变量。只能访问被final修饰的局部变量。

3、局部定义内部类代码

class Outer
{
    int x = 3;

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

        new Inner().function();

    }
}


class  InnerClassDemo3
{
    public static void main(String[] args) 
    {
        Outer out = new Outer();
        out.method(7);
        out.method(8);
    }

}
注:为什么上面的代码中打印的值为什么会改变呢?被final修饰的变量的值是不会被改变的。这里类调用方法使用完后,这时这个被final修饰的变量已经从栈内存中消失了,类再次调用这个方法时,已经是另一变量,所以可以重新被传值。

打印结果:4 4

二、匿名内部类
1、匿名内部类概述

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

2、匿名内部类利弊

匿名内部类的利与弊:
        好处:简化书写
        弊端:1、不能直接调用自己的特有方法、
                     2、不能做强转动作。
                     3、如果继承的父类或接口中有很多方法时,使用匿名内部类阅读性会非常差,且调用会很麻烦。所以匿名内部类中定义的方法有一般不超过3个。

3、练习补全代码

interface Inter
{
    void method();
}

class Test 
{
    //补足代码。通过匿名内部类。
    /*
    static class Inner implements Inter
    {
        public void method()
        {
            System.out.println("method run");
        }
    }
    */
    //匿名内部类补全
    static Inter function()
    {
        return new Inter()
        {
            public void method()
            {
                System.out.println("method run");
            }
        };
    }

}



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

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


        Test.function().method();


//      Inter in = Test.function();
//      in.method();


        /*show(new Inter()
        {
            public void method()
            {
                System.out.println("method show run");
            }
        });

    }

    public static void show(Inter in)
    {
        in.method();
    }
}

class InnerTest
{

    public static void main(String[] args)
    {
        new Object()
        {
            public void function()
            {
                System.out,println("InnerTest ------");
            }

        }.function();


    }*/
}

程序结果:

method run