面向对象高级

static

什么是static?

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

成员变量按照有无static修饰,分为两种:

  • 类变量:有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享。

        在什么情况下使用:数据只需要一份,且需要被共享时。

  • 实例变量(对象的变量):无static修饰,属于每个对象的。

           在什么情况下使用:每个对象都需要有一份,数据各不同。

    //1.类变量名的用法
        //类名.类变量(推荐)
        Student.name="袁华";

        //对象.类变量(不推荐)
        Student s1=new Student();
        s1.name="马冬梅";

        Student s2=new Student();
        s2.name="秋雅";
        System.out.println(s1.name);//结果为:秋雅

        //对象.实例变量
        s1.age=18;
        s2.age=25;
        System.out.println(s1.age);//结果为:18

 工具类是什么?

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

使用类方法来设计工具类的好处是什么?

  • 提高了代码复用性,调用方便,提高了开发效率。

注意:因为工具类不需要创建对象,建议将工具类的构造器私有。

使用类方法,实例方法的注意事项

  • 类方法中可以直接访问类的成员,不可以直接访问实例成员。
  • 实例方法中既可以直接访问类成员,也可以直接访问实例成员。
  • 实例方法中可以出现this关键字,类方法中不可以出现this关键字。

 代码块

代码块概述:

  • 代码块是类的五大成分之一(成员变量,构造器,方法,代码块,内部类)。

代码块分为两种:

静态代码块:

  • 格式:static{ }
  • 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会加载一次。
  • 作用:完成类的初始化,例如:对类变量的初始化赋值。

 实例代码块:

  • 格式:{ }
  • 特点:每次创建对象时,会执行实例代码,并在构造器前执行。
  • 作用:和构造器一样,都是用来完成对象的初始化,例如:对实例变量进行初始化赋值。

 设计模式

什么是设计模式?

  • 一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来,就叫做设计模式。

 单列设计模式:

确保一个类只有一个对象。

写法:

  • 把类的构造器私有。
  • 定义一个类变量记住类的一个对象。
  • 定义一个类方法,返回对象。

饿汉式单列特点:在获取类的对象时,对象已经创建好了。

懒汉式单例设计模式:

  • 拿对象时才开始创建对象。

写法:

  • 把类的构造器私有。
  • 定义一个类用于存储对象。
  • 提供一个类方法,保证返回的是同一个对象。

面向对象三大特征之二:继承 

什么是继承?

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

形式:

public B extends A{

} //其中B类叫作子类(派生类)
  //A类成为父类(基类或超类)

继承的特点和好处:

  • 子类能继承父类的非私有成员(成员变量,成员方法) 。
  • 减少重复代码的书写(好处)。

继承后成员的创建:

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

继承相关的注意事项

1.Java是单继承的:一个类只能继承一个直接父类;Java中的类不支持多继承,但是支持多层继承。

2.Object类是Java中所有类的祖宗。

 权限修饰符:

public , private ,protected , 缺省

什么是权限修饰符?
  • 就是用来限制类中的成员(成员变量,成员方法,构造器,代码块...)能够被访问的范围。
权限修饰符各自的作用:
修饰符在本类中在一个包下的其他类里任意包下的子类里任意包下的任意类里
private
缺失
protected
public

private < 缺省 < protected < public 

什么是方法重写?

  • 当子类觉得父类中某个方法不好时,或者无法满足自己的需求时,子类可以重写一个方法名称,参数列表一样的方法,去覆盖父类的这个方法,就是方法重写。
  • 注意:重写后,方法的访问,Java会遵循就近原则。 
方法重写的其他注意事项:
  • 重写小技巧:使用Override注解,他可以指定Java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
  • 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限。(public>protected>缺省)
  • 重写的方法返回值类型,必须与被重写方法返回值类型一样,或者范围更小。
  • 私有方法,静态方法不能被重写,如果重写会报错。

 1.在子类中访问其他成员(成员变量,成员方法),是依照就近原则

  • 先在子类局部范围找。
  • 然后子类成员范围找。
  • 然后父类成员范围找,如果父类范围还未找到就报错。

2.如果子父类中,出现重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类怎么办?

  • 可以通过super关键字,指定访问父类成员:super.父类成员变量/成员方法

子类构造器的特点 

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

子类构造器如何实现调用父类构造器的?

  • 默认情况下,子类全部构造器的第一行代码都是super ( )(写不写都有),他会调用父类的无参数构造器。
  • 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(.....),指定去调用父类的有参数构造器。

补充知识

  • 任意类的构造器中是可以通过this(....),去调用该类的其他构造器。 
public Student(String name,int age){
    this(name,age,"黑马学校"); //调用了下面的那个构造器
}
    public Student(String name, int age, String schoolName) {
        this.name = name;
        this.age = age;
        SchoolName = schoolName;
    }

this(....)和super(...)的注意事项:

  • this(...)和super(...)都要放在构造器的第一行,因此有了this(...)就不写有super(...),反之亦然。 

面向对象的三大特征之三:多态

认识多态: 

 1.什么是多态?

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

2.多态的具体代码体现:

3.多态的前提:

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

4.多态的一个注意事项:

多态是对象,行为的多态,Java中的属性(成员变量)不谈多态。 

使用多态的好处: 

1.好处:

  • 在多态形式下,右边对象是解耦合的,更便于扩展和维护。

people p1=new Student(); //右边部分可以随时更换
p1.run;

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

2.坏处: 

  • 多态下不能直接调用子类的独有方法。 

类型转换: 

1.类型转换:

  • 自动类型转换:父类 变量名 = new 子类();people p = new Student();
  • 强制类型转换: 子类 变量名=(子类)父类变量名;Student s=(Student) p;

2.强制类型转换的注意事项:

  • 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。
  • 运行时,如果发现对象的强转类型与真实类型不同,就会报类型转换异常(ClassCastException)的错误出来。
people p=new Teacher();
Student s=(Student) p;// 报错:ClassCastException

3.强转前,Java建议:

  • 使用instanceof关键字,判断当前对象的真实类型,再进行强转。 
public static void go(People p){
p.run;
if(p instanceof Student){
   Student s=(Student) p;
      s.test();
}else if(p instanceof Teacher){
     Teacher t=(Teacher) p;
      t.test();

final 

1.final:

  • final关键字是最终的意思,可以修饰(类,方法,变量 )。
  • 修饰类:该类被称为最终类,特点是不能被继承
  • 修饰方法:该方法被称为最终方法,特点是不能被重写
  • 修饰变量:该变量只能被赋值一次

2.final修饰变量的注意:

  • final修饰基本类型的变量,变量存储的数据不能被改变。
  • final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以改变的 。

3.常量 :

  • 使用了static final修饰的成员变量就称为常量 
  • 作用:通常用于记录系统的配置信息
public class Constant{
    public static final String SCHOOL_NAME="传智教育";

}

注意!常量名的命名规范:建议使用大写英文字母,多个单词用下划线连接起来。 

4.使用常量记录系统配置信息的优势,执行原理:

  • 代码可读性更好,可维护性更好。
  •  程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成字面量,这样可以保证使用常量和直接使用字面量的性能是一样的。

抽象类 

1.什么是抽象类?

  • 在Java中有一个关键字叫:abstract,他就是抽象的意思,可以用它修饰类,成员方法。 
  • abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
public abstract class A {
//抽象方法:必须用abstract修饰,只有方法签名,不能有方法体
    public abstract void run();
}

2.抽象类的注意事项,特点: 

  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
  • 类该有的成员(成员变量,方法,构造器)抽象类都可以有。
  • 抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
  • 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

3.抽象类的应用场景和好处? 

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

接口 

1.认识接口 

  •  Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊结构:接口。
public interface 接口名{
    //成员变量(常量)
    //成员方法(抽象方法)
}
  • 注意:接口不能创建对象;接口是用来被类实现(implements)的 ,实现接口的的类称为实现类。
修饰符 clsaa 实现类 implements 接口1,接口2,接口3...{
    
        }
  •  一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口,必须重写完全部全部接口的全部抽象方法,否则实现类就要定义成抽象类。

2.接口的好处(重点):

  • 弥补了类单继承的不足,一个类可以同时实现多个接口。
  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。一个类可以实现多个接口,一个接口也可以实现多个类。

3.JDK8开始,接口新增的方法:

  • 默认方法:使用default修饰,使用实现类的对象调用
  • 静态方法:使用static修饰,必须用当前接口名调用。
  • 私有方法:private 修饰,jdk9才开始有,只能在接口内部被调用。
  • 他们都会默认被public修饰。
    default void test1(){
            System.out.println("---默认方法---");
        }
        private void test2(){
            System.out.println("私有方法");
        }
        static void test3(){
            System.out.println("静态方法");
        }

    4.接口的多继承: 

  • 一个接口可以同时继承多个接口。 
     public interface E extends A, B,C{
            
      }//接口继承多个接口
    
    class M implements A,B,C{
    
    }//类实现多个接口

    5.接口的其他注意事项:

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

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

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

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

内部类 

内部类 :

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

    内部类有四种形式:

  • 成员内部类

  • 静态内部类

  • 局部内部类

  • 匿名内部类(重点)

1.成员内部类 

  • 就是类中的一个普通成员,类似于之前学的普通的成员变量,成员方法。
public class Outer{
        public class Inner{

        }
 }

如何创建对象:

外部类名.内部类名 对象名=new 外部类(...)new 内部类(...) 

(1)成员内部类中访问其他成员的特点:

  •  和之前学过的实例方法一样,成员内部类的实例方法中,同样可以直接访问外部类的实例成员、静态成员。
  • 可以在成员内部类的实例方法中,拿到当前外部类对象,格式是:外部类名.this

2.静态内部类

  • 有static修饰的内部类,属于外部类自己持有的。
 public class Outer{
    //静态内部类
    public static class Inner{
        
    }
    }

(1)创建对象的格式:

  • 外部类名.内部类名 对象名=new 外部类.内部类(...)  
  • Outer.Inner in=new Outer.Inner(...)

(2)静态内部类访问外部类成员的特点:

  • 可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员 

3.局部内部类 

  • 定义在方法中,代码块中,构造器等执行体中

4.匿名内部类 

  • 最终目的是简化代码。匿名内部类不是主动去去用,而是在有需求的时候去用
  • 就是一种特殊的局部内部类;所谓匿名,就是程序员不需要为这个类声明名字。

new 类接口(参数值){       

类体(一般是方法重写)

}

public class Animal {
    new Animal(){
        @Override
        public void cry{
            
        }
    }

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

3.作用:用于更方便创建一个子类对象。 

匿名内部类的开发场景:

  • 匿名内部类通常作为一个参数传输给对象。
    public static void main(String[] args) {
    //        Swimming s1 = new Swimming(){
    //            @Override
    //            public void swim() {
    //                System.out.println("狗🏊‍飞快~~~~");
    //            }
    //        };
    //        go(s1);
    
            go(new Swimming(){
                @Override
                public void swim() {
                    System.out.println("狗🏊‍飞快~~~~");
                }
            });
    
        }
    
        // 设计一个方法,可以接收swimming接口的一切实现类对象进来参加游泳比赛。
        public static void go(Swimming s){
            System.out.println("开始-----------------------");
            s.swim();
        }
    }
    
    
    
    // 猫和狗都要参加游泳比赛
    interface Swimming{
        void swim();
    }
    

    枚举

  • 枚举是一种特殊的类。

枚举类的格式:

修饰符 enum 枚举类名{

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

 其他成员......

}

注意:

  • 枚举类中的第一行,只能写一些合法的标志符(名称),多个名称用逗号隔开。
  • 这些名称,本质是常量,每个常量都会记住枚举类的一个对象。
  • 枚举类的构造器都是私有的,不能对外创建对象。
  • 枚举类提供一个一些额外的API。
  • 枚举都是最终类,不可以被继承。
  • 枚举类中,从第二行开始可以定义其他各种成员。
  • 编译器为枚举新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从Enum类中也会继承一些方法。

泛型 

?通配符,在使用泛型时可以代表一切类型 

1.认识泛型 

  • 定义类、接口、方法时,同时声明一个或者多个类型变量(如:<E>),称为泛型接口,泛型方法,他们统称为泛型。
public class ArrayList<E>{
      ...
}
  • 作用:泛型提供了在编译阶段约束所操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。
  • 泛型本质:把具体的数据类型作为参数传给类型变量。

2.泛型类 

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

}

    public class ArrayList<E>{
        
}

3.泛型接口 

修饰符 interface 接口名 <类型变量,类型变量...>{

}

    public interface A<E>{

}

4.泛型方法 

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

}
    public static <T> void test(T t){

}

通配符:

  • 就是“?”,可以在使用泛型的的时候代表一切类型;E、K、K、V是在定义泛型的时候使用的。

泛型的上下限:

  • 泛型上线:?extends Car : ?能接受的必须是Car或是其子类。
  • 泛型下线:? super Car : ?能接受的必须是Car或是其父类。

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

  • 泛型是工作在编译阶段的,一旦程序编译成class文件,class文件就不存在泛型了,这就是泛型擦除。
  • 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值