面向对象高级

面向对象三大特征:封装、继承、多态。

类的五大成员:成员变量、成员方法、构造器、代码块、内部类

一:static

statis修饰成员变量

static叫静态,可以修饰成员变量、成员方法。

成员变量分为类变量与实类变量(对象的变量)

类变量实类变量
特点

1.有static修饰,属于类,在计算器里只有一份会被类的全部对象共享。

2.可以用类名访问,也可以用对象访问(推荐用类名,因为更高效)

1.无static修饰,属于每个对象的。

2.只能用对象访问

 在开发中如果数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义为类变量记住。

static修饰成员方法

有static修饰的成员方法属于类,可用类名(推荐)与对象名访问

 无static修饰的成员方法属于对象,只能用对象访问。

工具类

工具类中的方法都是一些类方法,每个方法否是用来完成一个功能的,工具类是给开发人员共同使用的。

使用类方法来设计工具类优点:提高代码复用;调用方便,提高了开发效率

        实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存。

        类方法,直接用类名调用即可,调用方便,也能节省内存。

        工具类没有创建对象的需求,建议将工具类的构造器进行私有。

注意事项

        1、类方法中可以直接访问类的成员, 不可以直接访问实例成员。

        2、实例方法中既可以直接访问类成员,也可以直接访问实例成员。

        3、实例方法中可以出现this关键字,类方法中不可以出现this关键字的

 static的应用

代码块

静态代码块:

        格式:static{}

        特点:类加载时自动执行,由于类只会类只会加载一次,所以静态代码块也只会执行一次。

        作用:完成类的初始化,例如:对类变量的初始化赋值。 

实例代码块:

        格式:{}

        特点:每次创建对象时,执行实例代码块,并在构造器前执行。

        作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。

 单例设计模式

        (软件架构师必备知识)

设计模式

         一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。(设计模式有20多种,对应20多种软件开发中会遇到的问题。)

单例设计模式

        用处:确立只有一个类只有一个对象。

单例设计模式的实现方法有很多种,如饿汉式单例、懒汉式单例......

        eg1.饿汉式单例:在获取对象时,对象已经创建好了。

        写法: ●把类的构造器私有。

                    ●定义一个类变量记住类的一个对象。

                    ●定义一个类方法,返回对象。

//饿汉式单例
public class A{
    private static A a = new A();
    
    private A(){
    
    }
    
    public static A getObject(){
        return a;
    }
}

        eg2.懒汉式单例:拿对象时才开始创建对象

        写法: ●把类的构造器私有。

                    ●定义一个类变量用于存储对象。

                    ●定义一个类方法,这个方法要保证第一次调用时才创建一个对象,后面调用时都会

                      用这同一个对象返回。

//懒汉式单例
public class A{
    private static A a;
    
    private A(){
    
    }
    
    public static A getInstance(){
        if(a == null){
            a = new A();    
        }
        return a;
    }
}

二:继承

快速入门

继承是什么?

Java中提供了一个关键字extends,用这个关键字可以让一个类和另一个类建立起父子关系。

public class B extends A {

}

上列代码中的A为父类(也称基类或超类),B为子类(也称派生类)。

继承的特点

子类能继承父类的非私有成员(成员变量、方法)。能减少重复代码的编写

继承后对象的创建

子类的对象是由子类、父类共同完成的。  

继承相关的注意事项

权限修饰符

                public、private、protected、缺省(不写修饰符)

                权限修饰符是用来限制类中的成员(成员变量、成员方法、构造器、代码块...能够被访问 

        的范围。

修饰符在本类中同一个包下的其他类任意包下的子类里任意包下的任意类里
private
缺省
protected
public

                        范围:private <缺省< protected <public

单继承、Object类

        Java是单继承的,Java中的类不支持多继承,但是支持多层继承。

        Object是所有类的祖宗。任何一个类都是object发子类或子孙类。

方法重写

        当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。

 应用场景

        子类重写Object类的toString()方法,以便返回对象内容。

        注意事项

         ●重写小技巧:使用Override注解, 他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。

        ●子类重写父类方法时, 访问权限必须大于或者等于父类该方法的权限( public > protected>缺省)。

         ●重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。

         ●私有方法、静态方法不能被重写,如果重写会报错的。

子类中访问其他成员的特点

        1、在子类方法中访问其他成员(成员变量、成员方法) ,是依照就近原则的。在子类方法中访问子类名称可以用this,访问父类名称可以用super。(之类中访问方法也是依照就近原则,也可用super)

9f8ce1b92d2943c79402064dd46bf689.png

子类构造器的特点

        ●子类的全部构造器, 都会且必须先调用父类的构造器,再执行自己。

        ●默认情况下, 子类全部构造器的第一行代码都是 super()且写不写都有,它会调用父类的无参数构造器。

        ●如果父类没有无参 数构造器,则我们必须在子类构造器的第一行手写super(...) 指定去调用父类的有参数构造器。

补充知识

        任意类的构造器中,都可以通过this(..)去调用该类的其他构造器。(this(...)要放到构造器的第一行,且不能与super()共存。因为this()调用的构造器会先执行super())

三:多态

认识多态

        多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态。

    People p1 = new Student();
    p1.run();//编译看左边,运行看右边。
    People p2 = new Teacher();
    p2.run();//编译看左边,运行看右边。

        有继承/实现关系;存在父类引用子类对象;存在方法重写。

        多态是对象、行为的多态,Java中的属性(成员变量)不谈多态。(对于变量编译和运行都看左边)

多态的好处

        ●在多态形式下,右边对象是解耦合的,右边对象可以随时切换,后续业务随机改变,更便于扩展和维护。

        ●定义方法时,使用父类类型的形参,可以接收一切子类对象, 扩展性更强、更便利。

类型转换

        多态下不能使用子类的独有功能,可以进行类型转换解决。

                自动类型转换:父类 变量名 = new 子类();

                强制类型转换:子类 变量名 = (子类) 父类变量; 

强制类型转换的注意事项

        存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。

        运行时, 如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException) 的错误出来。

强转前,Java建议

        使用instanceof关键字,判断当前对象的真实类型,再进行强转。

    if(p1 instanceof Student) {
        Student s2 = (Student) p1;
        s2. test();
    }eLse {
        Teacher t2 = (Teacher) p1;
        t2. teach();

p1 instanceof Student中若p1的类型是Student着输出为true,否则为false。

四:抽象类

抽象类(不是必备的)

        ●在Java中有一个关键字叫: abstract, 它就是抽象的意思,可以用它修饰类、成员方法。

        ●abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。

public abstract class A {
//抽象方法:必须用abstract修饰,只有方法签名,一定不能有方法体!
    public abstract void run();

抽象类的注意事项、特点

        ●抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。

        ●类该有的成员(成员变量、方法、构造器)抽象类都可以有。

        ●抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。

        ●一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

 抽象类的好处

        ●父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态。

抽象类的常见应用场景:模板方法设计模式

模板方法设计模式解决的问题:方法中存在重复代码的问题。

写法:

        ●1、定义一个抽象类。

        ●2、在里面定义2个方法

                一个是模板方法:把相同代码放里面去。(建议使用final关键字修饰模板方法,防止子类重写。)

                一个是抽象方法:具体实现交给子类完成。

 五:接口

概述

写法(JDK8之前的版本)

        Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构:接口。(接口里只能有成员变量和成员方法。)

public interface InterfaceName{
//name为接口名
    //成员变量(默认为常量)
    //成员方法(默认为抽象方法)
}

注意事项 (JDK8之前的版本)

         接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类称为实现类。

        一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类。

                修饰符 class 实现类 implements 接口1,接口2,接口3,...{

                }

接口的好处

        ●弥补了类单继承的不足,一个类同时可以实现多个接口。

        ●让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。

其他细节

        1、JDK8开始,接口中新增的三种方法

        (1)默认方法:必须使用default修饰,默认会放public修饰。(实例方法,对象的方法必须用实现类的对象来访问。)

        (2)私有方法:必须使用private修饰。(JDK 9开始才支持;实例方法:对象的方法。)

        (3)静态方法:必须使用static修饰,默认会放public修饰。

        2、接口的多继承

        一个接口可以同时继承多个接口。(可以把多个接口合并成一个接口,便于实现类实现)

    public interface C extends B,A{

    }

        3、注意事项

        (1)一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承。

        (2)一个类实现多个接口,如果多个接口中存在方法签名冲突, 则此时不支持多实现。

        (3)一个类继承了父类,又同时实现了接口, 父类中和接口中有同名的默认方法,实现类会优先用父类的。

        (4)一个类实现了多个接口, 多个接口中存在同名的默认方法, 可以不冲突,这个类重写该方法即可。

六:内部类

内部类概述

        内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。当一个类的内部,包含了一一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。

成员内部类(了解)

概述

        就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法。(JDK 16开始才支持定义静态成员)

public class Out{
    Public class In{

    }
}

        创建内部类时要先创建外部类对象再创建内部类对象。

                例如:0ut.In t = new 0ut() .new In(); //Out为外部类类名,In为内部类类名

成员内部类中访问其他成员的特点

        ●和前面学过的实例方法一样,成员内部类的实例方法中,同样可以直接访问外部类的实例成员、静态成员。

        ●可以在成员内部类的实例方法中,拿到当前外部类对象,格式是:外部类名.this。

静态内部类(了解)

概述

        有static修饰的内部类,属于外部类自己持有。(与外部类的静态方法一样,可以访问外部类的静态成员,但不能直接访问外部类的实例成员)

public class Out{
    Public static class In{

    }
}

         静态内部类可以直接new出来

                例如:0ut.In t = new 0ut.In(); //Out为外部类类名,In为内部类类名

静态内部类中访问其他成员的特点

        ●和前面学过的静态方法一样,可以访问外部类的静态成员,但不能直接访问外部类的实例成员。

局部内部类(了解)

概述(鸡肋语法,看看就好)

        局部内部类是定义在在方法中、代码块中、构造器等执行体中。

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

    }

    public static void go(){

        class A{

        }

        abstract class B{

        }

        interface C{

        }
    }
}

匿名内部类(重点)

概述

        一种特殊的局部内部类;所谓匿名:指的是程序员不需要为这个类声明名字。

                格式:

                                               b1c4ecef0bb141099489462811d5381b.png

                 事例:

public class test {
    public static void main(String[] args){
        A t = new A(){
            @Override
            public void a(){
                System.out.println("AaA");
            }
        }
    }
}



abstract class A{
    public abstract void a();
}

 特点

        匿名内部类本质就是一个子类,并会立即创建出一个子类对象。

作用与应用场景

        用于更方便的创建一个子类对象。

        通常作为一个参数传输给方法

七:枚举

概括

        枚举是一种特殊的类。

        格式:

                修饰符enum枚举类名{

                        名称1,名称2,... ;

                        其他成员...

                        }

public enum A {
    X,Y,Z;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;
    
}

注: ●枚举类中的第一行, 只能写一些合法的标识符(名称),多个名称用逗号隔开。

        ●这些名称,本质是常量,每个常量都会记住枚举类的一个对象。

        ●其他成员:成员变量、成员方法、构造器、代码块、内部类。

特点

        ●枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。

        ●枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。

        ●枚举都是最终类, 不可以被继承。

        ●枚举类中, 从第二行开始,可以定义类的其他各种成员。

        ●编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法。(枚举类提供一些额外的API)

public class Time {
    public static void main(String[] args) {
        A[] as = A.values(); //拿到全部对象
        A a3 =A.valueOf("Z");
        System.out.println(a3.name());//Z
        System.out.println(a3.ordinal());//索引
    }
}

  枚举可以用来实现单例设计模式

public enum C {
    X;//单例
}

抽象枚举

        在枚举时要重写抽象方法

public enum B {
    X(){
        @Override
        public void g(){

        }
    }, Y(){
        @Override
        public void g(){
        }
    };

    public abstract void g();

}

八:泛型

概括

        ●定义类、接口、方法时,同时声明了一个或者多个类型变量(如: <E>),称为泛型类、泛型接口,泛型方法、它们统称为泛型。

        ●泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力。这样可以避免强制类型转换,及其可能出现的异常。

        ●泛型的本质: 把具体的数据类型作为参数传给类型变量。

泛型类、泛型接口

泛型类

格式

        修饰符 class 类名<类型变量,类型变量, ..>{

        }

        ●类型变量建议用大写的英文字母,常用的有: E、T、K、V等。

写法

//1.一个类型变量
public class ArrayList<E>{
    //……
}


//2.多个类型变量
public class ArrayList<E,T>{
    //……
}


//3.将泛型类限定
public class ArrayList<E extend A>{
    //这里的类型必须是A类或者是A的子类
    //……
}




public class A{

}

public class B extend A{

}

泛型接口

        泛型接口格式和写法与泛型类很相似,与泛型类相比class换成了interface。泛型接口的用法与接口很相似,方法也要重写。

      泛型方法

格式

        修饰符<类型变量,类型变量,...>返回值类型 方法名(形参列表) {

        }

    //泛型方法
    public static <T> void test(T t){

    }

    /*不是泛型方法
    public E get(int index){
    return(E) arr[index];
    }
    */

通配符

        在写泛型方法时可以用通配符:?在使用泛型的时候可以代表一切类型。(E T K V 是在定义泛型的时候使用)

    public static void A(ArrayList<?> eg){

    }
        
    //上边写法与下边的效果一样。
    public static <T> void A(ArrayList<T> leixing){

    }
? extends eg(上限)? super eg(下限)
类型要是eg或eg的子类类型要是eg或eg的父类

 泛型的擦除问题和注意事项 

        ●泛型是工作在编译阶段的,一旦程序编译成class文件, class文件中就不存在泛型了,这就是泛型擦除。

        ●泛型不支持基本数据类型, 只能支持对象类型( 引用数据类型)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值