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

单例定义,写法

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

实现步骤:

  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的使用
  • this
    this 代有当前类的引用,可以通过this.成员形式来访问成员变量和方法,可以通过this() 来调用本类的其它构造方法,但必须在第一行
  • super
    super:代表是父类的数据空间,并不是一个引用,因此没有对象可以指向可以通过 super.父类成员来访问父类的成员变量和成员方法;也可以通过super()来调用父类的构造方法,如果父类不存在无参的构造方法;在子类中必须调用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 接口

  • 定义格式

      interface 接口名{  全局常量; 抽象方法;  }
    
  • 特点
    1、 接口可以实现多继承

    2、 接口主要用于被实现,接口中的所有方法,在子类中必须全部实现

    3、在定义接口实现类的时,使用implements关键字,而且可以多实现

  • 扩展
    类和类是继承关系;类和接口是实现关系;通过继承可以得到继承体系统中基本功能;通过实现可以得到除继承之外的额外功能;注: 一个可以存在继承关系同时也可以存实现关系

案例

  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 狗();
   }
  • 多态的弊端
    只能使用父类中定义的方法,并且子类必须重写父类中的方法

  • 多态的好处
    1.有继承或者实现接口的关系

    2.重写或者实现父类(接口)的方法

    3.父类指针指向子类对象

多态案例

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()");
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,195评论 0 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,605评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,090评论 0 62
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,642评论 0 11
  • 《立意》 ——楼兰 在人间活出珍贵的尘 一定要去大海洗涤一次 跋山涉水的灵魂 温柔...
    燕返楼兰阅读 257评论 0 4