黑马程序员——面向对象<二> 笔记第四篇

来源:互联网 发布:java超市管理系统 编辑:程序博客网 时间:2024/04/30 20:43

Static关键字、单例设计模式、继承、抽象类

-----Java培训、Android培训、期待与您交流! -------

5 Static 关键字

5.1 Static 的访问方式

static修饰成员变量:static修饰的成员变量的数据就是共享的数据

 

static修饰的成员变量(静态的成员变量)的访问方式:

方式1:可以使用对象访问。

                            对象.属性名

方式2: 可以使用类名访问。

                            类名.属性名。

 

注意:

         1.非静态的成员变量只能使用对象进行访问,不能使用类名直接访问。

         2.千万不要为了方便访问数据而使用static修饰,只有数据真正是需要被共享的时候才使用static修饰。

推荐使用:类名直接访问。

 

static修饰函数

静态函数的访问方式:

         访问方式1:使用对象访问。

                            对象.函数名()

         访问方式2: 使用类名访问

                            类名.函数名();

 

 

5.2静态函数要注意的细节:

1. 静态函数可以使用对象或者类名调用,但是非静态函数只能使用对象进行调用。

2. 静态函数不能出现thissuper关键字

         原因:静态函数是可以使用类名直接调用的,而this关键字代表的是所属函数的调用者对象,这时候可能还没有对象的存在。

3. 静态函数可以直接访问静态的成员(成员变量、成员函数),但是不能直接访问非静态的成员。

         原因:非静态的成员变量是随着 对象的创建而存在的,静态函数是可以使用类名直接调用的,这时候可能还没有对象存在。

4. 非静态的函数是可以直接访问静态、非静态的成员的。

         原因: 非静态函数是需要对象调用的,对象存在的时候静态 数据以及非静态数据都已经存在了,所以可以。

 

什么时候使用static去修饰一个函数呢?

         如果一个函数没有直接访到非静态的成员,那么即可使用static修饰。常见的应用在:工具类的方法。

 

疑惑:静态的函数不能访问非静态的成员?

         错误,只要静态函数中存在着的对应的对象那么即可访问。

 

5.3非静态成员变量与静态的成员变量的区别:

作用上的区别:

         1. 非静态成员变量的作用:描述一类事物的属性。

         2. 静态的成员变量作用: 提供了一个共享的数据给所有对象使用。

数量上的区别:

         1.非静态的成员变量是随着对象的创建而 存在的,有 多少个对象就有多少份非静态的成员变量数据。

         2. 静态的成员变量数据在内存中仅有一份。是所有对象共享的数据。

生命周期的区别:

         1. 非静态的成员变量是随着对象的创建而存在,随着对象的消失而消失。

         2. 静态的成员变量数据是随着类文件的加载而存在,随着类文件的消失而消失。

 

5.4例子:

class Student{

    int id; //身份证

    String name; //名字

   

    //使用static修饰的数据就是共享的数据,可以被所有的Student对象共享使用,在内存中只有一份。

    static Stringcountry ="中国";//国籍

 

    //构造函数

    public Student(intid, Stringname){

       this.id =id;

       this.name =name;

    }

    //学习

    public void study(){

       System.out.println("好好学习,为称为高富帅做准备!!");

    }

}

 

class Demo5

{

    public static void main(String[] args)

    {

       Student s1 = new Student(110,"小强");

       Student s2 = new Student(119,"小红");

       s1.country ="小日本";

 

       System.out.println("身份证:"+s1.id+"名字:"+s1.name+"国籍:"+s1.country);  //小日本

       System.out.println("身份证:"+s2.id+"名字:"+s2.name+"国籍:"+s2.country);  //小日本

    }

}

分析:国籍没有static修饰时,运行结果是:(因为此时不是共享的数据)

//身份证:110名字:小强国籍:小日本

//身份证:119名字:小红国籍:中国

 

6 单例设计模式

解决的问题:保证一个类在内存中的对象唯一性。

比如:多程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的。

6.1 饿汉单例模式:

 

1. 私有化构造函数。

2. 在本类中创建该类的对象,并且使用一个私有静态的变量指向。

3. 提供有一个公共静态的方法获取本类的对象。

 

6.2懒汉单例设计模式:

1. 私有化构造函数。  

2. 声明本类的引用类型变量,但是不创建本类的对象。

3. 提供一个公共静态的方法获取本类的对象,获取对象之前先判断是否已经创建了该类的对象,如果没有创建,那么创建该类的对象并返回,如果已经创建了该类的对象,那么就直接返回即可。

 

推荐使用 : 饿汉式。

         因为懒汉式有可能出现线程安全问题,这是时候就无法保证该类在内存中只有一个对象了。

 

6.3 实现的代码

//懒汉式

class Single2{

 

    //声明本类的引用类型变量,但是不创建本类的对象。

    private static    Single2 s;

 

    //私有化构造函数

    private Single2(){}

 

    //提供有一个公共静态的方法获取本类的对象

    public static Single2 getInstance(){

       if(s==null){

           //没有创建就先创建本类对象

           s = new Single2();

       }

       returns;

    }

}

 

//饿汉式

class Single{

 

    //声明本类的引用类型变量指向本类的对象。

    private    static Single s = new Single();

   

    //第一步:私有化构造函数

    private Single(){}

   

    //提供有一个公共静态的方法获取本类的对象

    public static Single getInstance(){

       returns;

    }

}

 

class Demo10

{

    public static void main(String[] args)

    {

       Single2 s1 = Single2.getInstance();

       Single2 s2 = Single2.getInstance();

       System.out.println("两个对象是同一个吗?"+ (s1==s2));//true

    }

}

 

7 继承

继承的格式:      

class 类名1  extends类名2{

         }

 

继承的特点

1:描述类和类之间的关系

2:降低类和类之间的重复代码

3:降低对象和对象之间的代码重复使用静态变量

4:降低类和类之间的代码重复使用就继承

 

继承的好处

继承的出现提高了代码的复用性。

继承的出现让类与类之间产生了关系,提供了多态的前提。

 

继承要注意的细节:

1. 千万不要为了减少重复代码而去继承,只有两种事物真正存在着继承关系的时候才去继承。

2. 父类私有的成员不能被继承。

3. 父类的构造函数不能被继承。

4. 创建子类对象时,会先调用父类的构造函数。

 

疑惑:为什么创建子类对象的时候会先调用父类的构造函数呢,这样子做的意义在那?

意义就是:初始化从父类继承下来的属性。

 

7.1 super关键字:

super关键字代表的是父类空间的引用。

7.1.1 super关键字的作用:

1. 子父类存在着同名的成员时,在子类默认是访问子类的成员,可以通过super关键字指定访问父类的成员。

2. 创建子类对象时,默认是会先调用父类无参的构造方法,可以通过super关键字指定调用父类其他的构造方法。

3、主要存在于子类的方法中,用于指向子类对象中父类对象

 

7.1.2 super关键字要注意的细节:

1.  如果子类的构造函数没有指定调用父类构造函数,那么java编译器会在子类的构造函数中加上super();

2. super 调用父类的构造函数的时候必须是在构造函数中的第一个语句。

3. this 与super关键字调用构造函数时,不能同时出现在一个构造函数中,因为两个都需要在第一个语句。

 

7.1.3 super关键字与this关键字的区别:

1. super关键字只能在继承的关系下才能使用,this关键字不需要继承照样可以使用。

2. super关键字代表的是父类空间的引用。this代表的是所属函数的调用者对象。

3. super在子类的构造函数中是调用父类的构造函数,this关键字是构造函数中是调用本类的构造函数

4. super可以用作区分同名的子父类成员,可以指定访问父类的成员。 this关键字是用作区分同名的成员变量与局部变量的。

 

super思考

如果开发者自定义了一个类,没有显示的进行类的继承,那么该类中成员函数是否可以使用super关健健字?可以使用,继承了Object类,Object类是所有类的父类。

class Demo7 {

    public  void print(){

       System.out.println(super.toString());//继承了Object类

    }

    public static void main(String[] args){

       new Demo7().print();

       System.out.println();

        }

}

 

小知识点

子类对象查找属性或方法时的顺序:

    1:原则:就近原则。

如果子类的对象调用方法,默认先使用this进行查找,如果当前对象没有找到属性或方法,找当前对象中维护的super关键字指向的对象,如果还没有找到编译报错,找到直接调用。

 

重载和重写的不同

    1:重载(overload): 

       1:前提: 所有的重载函数必须在同一个类中

        2:特点:

             函数名相同,参数列表不同,与其他的无关(访问控制符、返回值类型)

       3:不同:

           个数不同 、 顺序不同、 类型不同

    2:重写(override):

         1:前提:继承

       2:特点:

            函数名必须相同、参数列表必须相同。

            子类的返回值类型要等于或者小于父类的返回值

 

7.2 instanceof 关键字

 

作用: 判断一个对象是否属于指定的类别。

使用前提: 判断的对象与指定的类别必须要存在着继承或者是实现的关系。

 

instanceof 使用格式:    

         对象instanceof  类

//动物类

class Animal{

    String name;//名字

    String color;//颜色

 

    //构造方法

    public Animal(Stringname,Stringcolor){

       this.name =name;

       this.color =color;

    }  

}

 

 

// 是属于动物中的一种

class Dog extends Animal{

    public Dog(Stringname ,Stringcolor){

       super(name,color);

    }

 

    //咬人

    public void bite(){

       System.out.println(name+"狠狠的咬人!!");   

    }

}

 

//也是属于动物中的一种

class Fish extends Animal  {

    //构造方法。

    public Fish(Stringname,Stringcolor){

       super(name,color);

    }

    public void swing(){

       System.out.println(name+"在水里游....");

    }

}

 

 

class Demo8

{

    public static void main(String[] args)

    {

       Animal a = new Animal("动物","黑色");

       Dog d = new Dog("哈士奇","白色");

       System.out.println("动物都属于狗类吗?"+(ainstanceof Dog));

       System.out.println("狗是属于动物类别吗?"+(dinstanceof Animal)); // 判断对象是否属于狗类型,如果是返回true,否则返回false.

    }

}

 

7.3 final 关键字

作用:增强数据的安全性。

1. final修饰一个基本类型的变量时,该变量不能重新赋值。

2. final 修饰一个引用类型变量时,该变量不能重新指向新的对象。

3. fianl 修饰一个方法的时候,该方法不能被重写。

4. fianl 修饰一个类的时候,该类不能被继承。为最终的类

 

常量的修饰符: public static final  

常量的命名规范:全部字母大写,单词与单词之间使用下划线分隔。

 

final class Circle{  //狗剩

    public static final double PI = 3.14 ; //PI的值应该是固定的。

    //半径

     int r;

    public Circle(intr){

       this.r =r;  

    }

 

    public Circle(){}

    //获取面积

    public final void getArea(){

       System.out.println("面积是:"+PI*r*r);

    }

}

 

 

class Demo extends Circle   //final 修饰的类不能被继承

{

    public static void main(String[] args)

    {

       //创建一个圆形对象。

       final Circlec =new Circle(4);

       test(c);

       /*

       c.PI = 0.0; // 狗娃

       c.getArea();

       //System.out.println("Hello World!");

       */

    }

 

    public static void test(Circle c){ 

       //c变量重新指向一个新的对象。

       c  = new Circle(5);

    }

}

 

8 抽象类

8.1抽象类的应用场景:

         描述一类事物的时候,发现该类事物目前确实存在着某种行为,但是目前这种行为是不具体的,那么这时候我们可以把这种行为描述抽象的行为,只抽取这种行为功能的声明,而不实现该功能行为,这时候我们可以使用抽象类描述。

 

抽象类的好处:强制子类去实现指定的方法。

抽象类主要为了提高代码的复用性,让子类继承来使用。

 

8.2抽象类要注意的细节:

1. 如果一个类有抽象的方法,那么该类就必须使用abstract修饰。

2. 非抽象类继承抽象类的时候,必须要把抽象类的所有抽象方法实现。(抽象方法具体化)

3. 抽象类可以存在非抽象方法与抽象方法的。

4. 抽象类可以不存在抽象的方法。

5. 抽象类不能创建对象。

         疑问:为什么抽象类不能创建对象呢?

         抽象类如果创建了对象,抽象类就调用对应的方法了,抽象类是具有抽象方法的,如果调用了抽象的方法(抽象方法内没有具体功能),这样子是没有意义的。

6. 抽象类是存在构造函数的。

         疑问:抽象类不能创建对象,那么存在构造函数的意义何在呢?

         抽象的构造函数是提供给其子类使用的,因为需要初始化从父类继承下来的属性数据。

 

 

8.3 abstract与其他修饰符的关系:

final与abstract不能共存:

         final:它的作用  修饰类代表不可以继承  修饰方法不可重写

         abstract修饰类就是用来被继承的,修饰方法就是用来被重写的。

Static  static修饰的方法可以用类名调用,

                    对于abstract修饰的方法没有具体的方法实现,所有不能直接调用,也就是说不可以与static共存。

private

         private修饰的只能在本类中使用,

         abstract方法是用来被子类进行重写的,有矛盾所有不能共存.

 

//动物类

abstract class Animal {

    String name ;

    String color;

    //构造函数

    public Animal(Stringname ,Stringcolor){

       this.name =name;

       this.color =color;

    }

 

    // 抽象的方法

    public abstract final  void run(); //抽象的行为。 final修饰后的方法不能被重写

    //非抽象的方法。

    public void eat(){

       System.out.println("吃粮食..");

    }

}

 

 

// 非抽象类

class Dog extends Animal{

 

    //构造函数

    public Dog(Stringname,Stringcolor){

       super(name,color);

    }

    public  void run()//run方法被final修饰

       System.out.println(name+"四条腿跑得很快...");

    }

}

 

 

// 非抽象类    抽象类

class Fish extends Animal{

   

    public Fish(Stringname,Stringcolor){

       super(name,color);

    }

 

    public  void run(){ //run方法被final修饰

       System.out.println(name+"摇摇尾巴游啊游!!...");

    }

}

 

 

class Demo10

{

    public static void main(String[] args)

    {

       /*

       //System.out.println("Hello World!");

       //创建一个狗对象

       Dog dog = new Dog("牧羊犬","棕色");

       dog.run();

 

       //创建一个鱼对象

       Fish f = new Fish("锦鲤","金色");

       f.run();

       */

 

       //创建一个抽象类的对象。

       //Animal a = new Animal("动物","黑色");

       //a.run();

    }

}

 


0 0
原创粉丝点击