抽象类

单例模式,this,super,final,接口,抽象类以及多态

2016-12-22  本文已影响50人  向日花开

单例定义,写法

单例模式: 在程序运行其间,保存类对象只会创建一次(确保只有一个实例)

实现步骤:

  1. 私有化构造方法

  2. 提供本类的实例对象(好多种)

  3. 向类的外部提供一个方法,获取类的对象

为什么使用单例:1.能避免实例重复创建 2.应用于避免存在多个实例引起程序逻辑错误的场合3.较节约内存

单例写法案例

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

          Singleton tv1 = Singleton.getInstance2("张三");
          Singleton tv2 = Singleton.getInstance2("李四");

          System.out.println(tv1 == tv2);//true//比较的是内存地址
          tv2.speak();//张三
      }
  }


  class Singleton {
      String name;

      //1.私有化构造方法
      private Singleton(String name) {
          this.name = name;
      }

      //2.提供本类的对象
      private static Singleton singleton1;


          //写法一:同步懒汉式,3.向外部提供可访问的方法,并返回当前类的对象
          public synchronized Singleton getInstance1(String name) {
              if (singleton1 == null) {
                  singleton1 = new Singleton(name);
              }
              return singleton1;
          }

      //写法二:优化后的懒汉式,方法一中的同步冗余,3.向外部提供可访问的方法,并返回当前类的对象
      public static Singleton getInstance2(String name) {
          if (singleton1 == null) {
              synchronized (Singleton.class) {
                  if (singleton1 == null) {
                      singleton1 = new Singleton(name);
                  }
              }
          }
          return singleton1;
      }

      ////////////////////////////////////////////
      //写法三:饿汉式2.提供本类的对象
      private static Singleton singleton3 = new Singleton("default");

      //3.向外部提供可访问的方法,并返回当前类的对象
      public static Singleton getInstance3() {
          return singleton3;
      }

      ////////////////////////////////////////////
      //写法四:内部类

      /**
       * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,
       * 而且只有被调用到才会装载,从而实现了延迟加载
       *
      private static class SingletonHolder {
          //2.提供本类的对象
          private static final Singleton instance = new Singleton("default");
      }

      //3.向外部提供可访问的方法,并返回当前类的对象
      public static Singleton getInstance4() {
          return SingletonHolder.instance;
      }


      ////////////////////////////////////////////
      public void speak() {
          System.out.println(name);
      }

  }

super 、this关键字

方法的重写:首先存在继承关系,然后方法名、参数、返回数据类型都与父类中方法名和参数相同。父类的私有方法不能被重写,静态只能覆盖静态。

this和super的使用

注: super() 和 this()不能同时出现,this和super不能出现静态成员方法中

案例

public class Demo {
    public static void main(String[] args){
        Parent parent=new Child(); //多态
        parent.say("您好");//父类说...您好
                          //子类说...您好

        parent.print(); //父类打印...
    }
}

class Parent {

    public void say(String msg) {
        System.out.println("父类说..." + msg);
    }

    public static void print() {
        System.out.println("父类打印...");
    }

}


class Child extends Parent {

    //重写父类的方法可以扩展功能
    public void say(String msg) {
        super.say(msg); //调用父类的成员方法

        System.out.println("子类说..." + msg);
    }

    public static void print() { //重写父类的静态方法时,只能以静态的方式覆盖
        //super.print(); //this和super不能出现在静态成员方法中
        System.out.println("子类打印...");
    }

}

final关键字

final(C++ const): 最终的,修饰类、成员方法、成员变量、局部变量。
注意:

1、final修饰的类,不能被继承

2、final修饰的方法,不能被重写

3、final修饰的成员变量(局部变量),不能被修改

4.String类就是final 修饰的类

final案例

public class Demo {

    public static void main(String[] args) {
        Circle c = new Circle(5);
        System.out.println(String.format("%.2f", c.area()));
    }
}

final class Test1 { //这是一个最终的类

}

/*
class C_Test extends Test1{ //不能继承final类

}
*/

class Test2 {

    public final void area() { //final修饰的方法不能被子类重写

    }
}

class B_Test2 extends Test2 {
    final int a = 10;

    public void area(final int w, final int h) {
        //a=90;//变量不能被修改
        //w=w*h;

        final Test2 t2 = new Test2();

        //final 修饰的引用不能再指向其它对象
        //t2=new Test2();  //出错
    }
}

//求圆的面积 s=PI*r*r
class Circle {
    public static final double PI = 3.1415;

    private int radius; //半径


    public Circle(int radius) {
        this.radius = radius;
    }

    public double area() {
        return PI * radius * radius;
    }

}

抽象类 abstract class

abstract: 抽象的,包含抽象方法的类叫抽象类,abstract修饰的类;抽象类也是一个类,只不过没有足够的信息来描述某一事物行为的方法;特点:

1、抽象类不能创建对象,因为其中包含了未实现的抽象方法

2、继承抽象类的子类,如果没有实现抽象方法,则这个类也是抽象类

注意:

抽象类一定是父类,不然没有存在的意义。

抽象类是有构造方法,用于初始化类中的成员变量

相同点: 都是类,可以被继承

不同点:抽象类不可以创建对象,普通类可以创建对象;抽象类可以包含抽象方法,普通类不能包含抽象方法

另,abstract不能与以下关键字组合使用:

final: final修饰的类不能被继承,abstract类必须要被继承(不然没意义)

static: 静态方法可以直接通过类名被调用,抽象方法不能被调用

private: 私有方法不能被重写,抽象方法必须被重写

案例

public class Demo {

    public static void main(String[] args) {

       //Circle1 c=new Circle1(6); //不能创建抽象类的对象

        Rectangle r=new Rectangle(8,10);

        System.out.println(r.area());//80.0
    }
}
abstract class Shape{
    public abstract double area();
}

abstract class Circle1 extends Shape{
    public static final double PI=3.14;
    private int radius;

    public Circle1(){}
    public Circle1(int radius){ this.radius=radius;}

    public  abstract double area();
}

class Rectangle extends Shape{
    private int width;
    private int height;

    public Rectangle(int width,int height){
        this.width=width;
        this.height=height;
    }

    public double area(){ //实现抽象方法
        return width*height;
    }
}

abstract class  Test3{ //注:抽象类中可以不存在抽象方法

}

class C_Test3 extends Test3{

}

interface 接口

案例

  public class Demo{

      public static void main(String[] args) {
          System.out.println(AllAnimalListener.type); //可以通过接口名直接访问全局变量//动物

          //AllAnimalListener all=new AllAnimalListener(); //接口不能创建对象

          Listener listener = new Animal();
          listener.walk();//动物在走...

          AllAnimalListener animalListener = new Animal();
          animalListener.run();//最佳最近调用原则:多态性中体现//动物在跑...
      }
  }

  interface Listener {
      //声明全局常量

      void walk();
  }

  interface CatListener {
      void talk();
  }

  //接口的多继承,因为所有接口中方法都没有实现,不会存在调用的不确定性问题
  interface AllAnimalListener extends CatListener, Listener {
      static final String type = "动物";

      void run();
  }

  class Animal implements AllAnimalListener, CatListener, Listener { //一个类可实现多个接口

      //必须要实现或重写接口的方法 CatListener
      @Override
      public void talk() {
          System.out.println(type + "在说话...");
      }

      //必须要实现或重写接口的方法 Listener
      @Override
      public void walk() {
          System.out.println(type + "在走...");
      }

      //必须要实现或重写接口的方法 AllAnimalListener
      @Override
      public void run() {
          System.out.println(type + "在跑...");
      }
  }

Java多态

对象的多态性: 多种形态,父类类型的引用指向子类对象,多态的前提:存在继承或实现关系

  class 动物{
   public void eat(){}
   }
class 猫 extends 动物{
   }
   常态:  猫看成是猫   猫 c=new 猫();
   多态:  猫是动物     动物 d=new 猫(); //第一种方式体现多态

   void 方法名(动物 d){  //第二种方式体现多态
    d.eat();
    }
  动物 方法名(int type){ //第三种方式体现多态
  if(type==1){
    return new 猫();
    }
   return new 狗();
   }

多态案例

public class Demo {
    public static void main(String[] args) {
        Cat cat = new Cat();//常态
        cat.eat();//猫吃鱼
        cat.catchMouse();//猫抓老鼠

        Animal1 a1 = new Cat(); //多态,第一种方式
        //a1.eat();
        //a1.catchMouse();//出错,因为父类中没有声明此方法

        Animal1 a2 = new Dog();//多态
        //a2.eat();

        eat(a1);//猫吃鱼
                //小猫正在吃。。。。
        eat(a2);//狗吃骨头
                //小狗正在吃。。。。
    }

    public static void eat(Animal1 animal) { //第二种方式体现多态性
        animal.eat(); //调用是Animal实际对象的方法,实际对象可能是Cat、Dog的类对象

        //通过instanceof关键字判断对象是哪一种类型的对象
        if (animal instanceof Cat) {
            System.out.println("小猫正在吃。。。。");
        } else {
            System.out.println("小狗正在吃。。。。");
        }

    }
}


abstract class Animal1 {
    public abstract void eat(); //虚方法
}

class Cat extends Animal1 {
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}

class Dog extends Animal1 {
    public void eat() {
        System.out.println("狗吃骨头");

    }

    public void kanjia() {
        System.out.println("看家");
    }
}

向上,向下转型

多态第三种体现方式,向上转型: 子类类型向父类类型转换(自动--多态的体现);向下转型: 当子类中扩展的方法被调用时,需要将对象转成子类类型对象

案例

/**
 * 注意: 为了减少错误,在强转之前,可以通过instanceof判断对象是否为某一种类型
 */
public class Demo{
    public static void main(String[] args) {


        Animal2 a1 = new Cat1(); //向上转换,子类对象转成父类对象

        eat(a1);//猫吃鱼
        //小猫正在吃。。。。
        // 猫抓老鼠

        Animal2 a2 = newAnimal(Animal2.TYPE_DOG);
        eat(a2);//狗吃骨头
        //小狗正在吃。。。。
        //看家

    }

    public static void eat(Animal2 animal) { //第二种方式体现多态性
        animal.eat(); //调用是Animal实际对象的方法,实际对象可能是Cat、Dog的类对象

        //通过instanceof关键字判断对象是哪一种类型的对象
        if (animal instanceof Cat1) {
            System.out.println("小猫正在吃。。。。");


            //需要调用Cat中扩展的方法
            Cat1 c = (Cat1) animal; //向下转型,父类对象向子类对象转型
            c.catchMouse();

        } else {
            System.out.println("小狗正在吃。。。。");

            Dog1 d = (Dog1) animal;
            d.kanjia();
        }

    }

    //第三种体现多态性,根据类型创建某一动物的对象
    public static Animal2 newAnimal(int type) {
        if (type == Animal2.TYPE_CAT) {
            return new Cat1();
        } else if (type == Animal2.TYPE_DOG) {
            return new Dog1();
        }

        return null;
    }

}

abstract class Animal2 {
    public static final int TYPE_CAT = 1;
    public static final int TYPE_DOG = 2;

    public abstract void eat(); //虚方法
}

class Cat1 extends Animal2 {
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}

class Dog1 extends Animal2 {
    public void eat() {
        System.out.println("狗吃骨头");

    }

    public void kanjia() {
        System.out.println("看家");
    }
}

接口的多态体现

接口是一种引用数据类型,定义接口的引用指向到接口实现类对象, 则是接口体现多态的方式

/**
 * 接口中的多态
 * 接口与多态
 *
 */
public class Demo {

    public static void main(String[] args) {
        Listen l1 = new Animal3(); //接口的多态

        l1.walk();//动物在走
        l1.music();//动物在唱歌

        Listen l2 = new Person();
        l2.walk();//人在走
        l2.music();// 人在唱歌
    }
}

interface Listen {
    void music();

    void walk();

}

class Animal3 implements Listen {


    @Override
    public void music() {
        System.out.println("动物在唱歌");
    }

    @Override
    public void walk() {
        System.out.println("动物在走");
    }
}

class Person implements Listen {

    @Override
    public void music() {
        System.out.println("人在唱歌");
    }

    @Override
    public void walk() {
        System.out.println("人在走");
    }
}

多态中的调用

案例

public class Demo{
    public static void main(String[] args) {
        Parent1 parent1 = new Child1();
        System.out.println("num->" + parent1.num); //成员变量的结果:在编译和运行都看父类//num->20

        parent1.say();//运行哪一个方法,编译时看父类,运行时看子类//Child1 say()

        parent1.fun();//运行哪一个方法:(静态)编译和运行时都看父类//Parent1 static fun()


        Child1 child1 = (Child1) parent1;
        System.out.println("num->" + child1.num);//num->50
        child1.say();//Child1 say()
        child1.fun();//Child1 static fun()
    }
}

class Parent1 {
    int num = 20;

    public void say() {
        System.out.println("Parent1 say()");
    }

    public static void fun() {
        System.out.println("Parent1 static fun()");
    }

}

class Child1 extends Parent1 {
    int num = 50;

    public void say() {
        System.out.println("Child1 say()");
    }

    public static void fun() {
        System.out.println("Child1 static fun()");
    }

}
上一篇下一篇

猜你喜欢

热点阅读