Loading

Java学习笔记(2)

1.继承
继承是面向对象当中的一个概念,与多态,封装共为面向对象的三个基本特征。
如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。
看如下代码,不使用继承
设计一个物品类,包含名字和价格属性。

public class Item {
    String name;
    int price;
}

设计一个武器类,包含名字,价格和攻击力三种属性。

public class Weapon{
    String name;
    int price;
    int damage; //攻击力

}

我们可以看到,与Item类相比,Weapon类只多了一个攻击力的属性。可能多写一个属性你会觉得没什么,但是相同的东西多了,你写的一定会很不舒服。
所以我们使用extends关键字来使用继承。

public class Weapon extends Item{
    int damage; //攻击力

    public static void main(String[] args) {
        Weapon infinityEdge = new Weapon();
        infinityEdge.damage = 65; //damage属性在类Weapon中新设计的

        infinityEdge.name = "无尽之刃";//name属性,是从Item中继承来的,就不需要重复设计了
        infinityEdge.price = 3600;
    }
}

继承的作用:
继承可以减少重复的代码。比如父类已经提供的方法,子类可以直接使用,不必再去实现。
继承是多态性的前提。当然使用继承的同时也提高了类的耦合度。

继承的特性:
子类拥有父类非private的属性,方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。 子类可以用自己的方式实现父类的方法。

2.多态
多态(Polymorphism)按字面的意思就是“多种状态”。我们先看两段代码,先多态有个基本的认识。
先写两个类,分别代表生命药水和法力药水,分别继承于物品类(Item)。

public class LifePotion extends Item {
    public void effect(){
        System.out.println("血瓶使用后,可以回血");
    }
}
public class MagicPotion extends Item{

    public void effect(){
        System.out.println("蓝瓶使用后,可以回魔法");
    }
}

假设我们设计了一个英雄类,它要具备使用生命药水和法力药水两种功能,如果我们不使用多态。那代码就是下面这样。

public class Hero {
    public String name; 
    protected float hp;

    public void useLifePotion(LifePotion lp){
        lp.effect();
    }
    public void useMagicPotion(MagicPotion mp){
        mp.effect();
    }

    public static void main(String[] args) {

        Hero garen =  new Hero();
        garen.name = "盖伦";

        LifePotion lp =new LifePotion();
        MagicPotion mp =new MagicPotion();

        garen.useLifePotion(lp);
        garen.useMagicPotion(mp);

    }

}

代码中我们可以看到,我们为了实现这两个功能,分别写了两个特定的方法去实现。但是事实上我们一个英雄可能不止使用这两种物品,难道我们要写很多很多个方法去实现吗?这当然不太靠谱,所以一定会有其它方式来实现。
看下面这段代码,我们使用多态的方式来实现上述功能。

import property.Item;
import property.LifePotion;
import property.MagicPotion;

public class Hero {
    public String name; 
    protected float hp;

    public void useItem(Item i){
        i.effect();
    }

    public static void main(String[] args) {

        Hero garen =  new Hero();
        garen.name = "盖伦";

        LifePotion lp =new LifePotion();
        MagicPotion mp =new MagicPotion();

        garen.useItem(lp);
        garen.useItem(mp);      

    }

}

可以看到,我们只使用了一个方法就完成了两个功能的实现,想要使用生命药水的时候,我们就可以在uesitem方法填LifePotion这个参数。useitem方法的参数填的是Item类,而LifePotion继承自Item类,所以我们参数填LifePotion完全没有问题。

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

多态的作用:
建立一个父类对象的引用,它所指对象可以是这个父类的对象,也可以是它的子类的对象。java中当子类拥有和父类同样的函数,当通过这个父类对象的引用调用这个函数的时候,调用到的是子类中的函数。

Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
(http://www.cnblogs.com/chenssy/p/3372798.html)

3.单例模式
单例模式有叫做 Singleton模式,指的的一个类,在一个JVM里,只有一个实例存在。
下面介绍两种常见的单例模式的写法
饿汉式单例模式:

public class GiantDragon {

    //私有化构造方法使得该类无法在外部通过new 进行实例化
    private GiantDragon(){

    }

    //准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个

    private static GiantDragon instance = new GiantDragon();

    //public static 方法,提供给调用者获取12行定义的对象
    public static GiantDragon getInstance(){
        return instance;
    }

}

GiantDragon 提供了一个public static的getInstance方法,外部调用者通过该方法获取定义的对象,而且每一次都是获取同一个对象。 从而达到单例的目的。
饿汉式单例模式,无论如何都会创建一个实例。

懒汉式单例模式:

public class GiantDragon {

    //私有化构造方法使得该类无法在外部通过new 进行实例化
    private GiantDragon(){        
    }

    //准备一个类属性,用于指向一个实例化对象,但是暂时指向null
    private static GiantDragon instance;

    //public static 方法,返回实例对象
    public static GiantDragon getInstance(){
        //第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
        if(null==instance){
            instance = new GiantDragon();
        }
        //返回 instance指向的对象
        return instance;
    }

}

懒汉式单例模式与饿汉式单例模式不同,只有在调用getInstance的时候,才会创建实例。

什么时候使用饿汉式,什么时候使用懒汉式?
饿汉式是立即加载的方式,无论是否会用到这个对象,都会加载。
如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。

懒汉式,是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量(鉴于同学们学习的进度,暂时不对线程的章节做展开)。
使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式。

单例模式三元素:
1. 构造方法私有化
2. 静态属性指向实例
3. public static的 getInstance方法,返回第二步的静态属性。

最后介绍一下其他几种单例模式的写法
http://cantellow.iteye.com/blog/838473

posted @ 2017-10-22 13:56  Xianhao  阅读(53)  评论(0编辑  收藏  举报