JAVA面向对象二

static(静态) 关键字
用于修饰成员(成员变量和成员函数)
被修饰的成员具备以下特点
随着类的加载而加载
优先于对象存在
被所有对象所共享
可以直接被类名调用
类/静态变量存在于方法区中(共享区)
使用注意
静态方法只能访问静态成员
静态方法不可写this、super等关键字

什么使用静态?
要从两方面下手:
因为静态修饰的内容有成员变量和函数。
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
对象中的特有数据要定义成非静态存在于堆内存中。
什么时候定义静态函数呢?
当功能内部没有访问到肺静态数据(对象的特有数据)
那么该功能可以定义成静态的。

    /* 
    静态:static。 
    用法:是一个修饰符,用于修饰成员(成员变量,成员函数). 
    当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外, 
    还可以直接被类名调用。类名.静态成员。 
     
     
    static特点: 
    1,随着类的加载而加载。 
       也就说:静态会随着类的消失而消失。说明它的生命周期最长。 
     
    2,优先于的对象存在 
    明确一点:静态是先存在。对象是后存在的。 
     
    3,被所有对象所共享 
    4,可以直接被类名所调用。 
     
    实例变量和类变量的区别: 
    1,存放位置。 
        类变量随着类的加载而存在于方法区中。 
        实例变量随着对象的建立而存在于堆内存中。 
    2,生命周期: 
        类变量生命周期最长,随着类的消失而消失。 
        实例变量生命周期随着对象的消失而消失。 
     
     
     
    静态使用注意事项: 
    1,静态方法只能访问静态成员。 
        非静态方法既可以访问静态也可以访问非静态。 
    2,静态方法中不可以定义this,super关键字。 
        因为静态优先于对象存在。所以静态方法中不可以出现this。 
    3,主函数是静态的。 
         
     
     
    静态有利有弊 
    利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。 
        可以直接被类名调用。 
    弊端:生命周期过长。 
          访问出现局限性。(静态虽好,只能访问静态。) 
    */  
      
    class Person  
    {  
        String name;//成员变量,实例变量。  
        static String country = "CN";//静态的成员变量,类变量。  
        public static void show()  
        {  
            System.out.println("::::");  
            this.haha();  
        }  
        public void haha()  
        {}  
    }  
      
    class  StaticDemo  
    {  
        public static void main(String[] args)   
        {  
            Person p = new Person();  
            //p.name = "zhangsan";  
            //p.show();  
      
            //System.out.println(p.country);  
      
            //System.out.println(Person.country);  
      
            Person.show();  
        }  
    }  
对象的初始化
    class Person  
    {  
        private Person(){}  
        private String name = "hah";  
        private int age;  
        private static  String country = "cn";  
        Person(String name,int age)  
        {  
            this.name = name;  
            this.age = age;  
        }  
          
        {  
            System.out.println(name+".."+age);  
        }  
        public void setName(String name)  
        {  
            this.name = name;  
        }  
      
        public void speak()  
        {  
            System.out.println(this.name+"..."+this.age);  
        }  
      
        public static void  showCountry()  
        {  
            System.out.println("country="+Person.country);  
            Person.method();  
        }  
        public static void method()  
        {  
            System.out.println("method run");  
        }  
      
    }  
      
    class  PersonDemo  
    {  
        public static void main(String[] args)   
        {  
            Person p = new Person("zhangsan",20);  
            p.setName("lisi");  
            new Person();  
        }  
    }  
    /* 
    Person p = new Person("zhangsan",20); 
     
    该句话都做了什么事情? 
    1,因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。 
    2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。 
    3,在堆内存中开辟空间,分配内存地址。 
    4,在堆内存中建立对象的特有属性。并进行默认初始化。 
    5,对属性进行显示初始化。 
    6,对对象进行构造代码块初始化。 
    7,对对象进行对应的构造函数初始化。 
    8,将内存地址付给栈内存中的p变量。 
     
    */  

1.继承

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

作用:

提高了代码的复用性

让类与类之间产生了关系,有了这个关系,才有了多态的特性

注意点:

千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承

JAVA语言中只支持单继承,不支持对继承(同一个类继承多个类),多继承容易带来安全隐患,当多个父类中定义多个相同功能,DNA功能内容不同,子类不确定要运行哪一个。

但是JAVA保留了这种机制,并用一种形式体现,多实现。

如何使用继承体系的功能

想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能,通过了解功能,就可以知道该体系的基本功能,那么这个体系就可以基本使用了

在具体调用时为什么要创建最子类的对象

一是因为有可能父类不能创建对象

二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。

    /* 
    将学生和工人的共性描述提取出来,单独进行描述, 
    只要让学生和工人与单独描述的这个类有关系,就可以了。 
     
  
    class C 
    { 
        void demo1(){} 
    } 
     
     
    class A extends C 
    { 
        //void demo1(){} 
        void demo2(){} 
    } 
     
    class B extends C 
    { 
        //void demo1(){} 
        void demo3(){} 
    } 
     
    Java语言中:java只支持单继承,不支持多继承。 
     
    因为多继承容易带来安全隐患:当多个父类中定义了相同功能, 
    当功能内容不同时,子类对象不确定要运行哪一个。 
    但是java保留这种机制。并用另一种体现形式来完成表示。多实现。 
     
     
    java支持多层继承。也就是一个继承体系 
     
    如何使用一个继承体系中的功能呢? 
     
    想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。 
    通过了解共性功能,就可以知道该体系的基本功能。 
    那么这个体系已经可以基本使用了。 
    那么在具体调用时,要创建最子类的对象,为什么呢? 
    一是因为有可能父类不能创建对象, 
    二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。 
     
     
    简单一句话:查阅父类功能,创建子类对象使用功能。 
     
     
     
    class A 
    { 
        void show() 
        { 
            System.out.println("a"); 
        } 
    } 
    class B 
    { 
        void show() 
        { 
            System.out.println("b"); 
        } 
    } 
     
    class C extends A,B 
    {} 
     
    C c = new C(); 
    c.show(); 
     
    聚集:has a 
     
    聚合: 
     
    组合: 
     
    */  
      
    class Person  
    {  
        String name;  
        int age;  
      
    }  
    class Student extends Person  
    {  
            void study()  
        {  
            System.out.println("good study");  
        }  
    }  
      
    class Worker extends Person  
    {  
        void work()  
        {  
            System.out.println("good work");  
        }  
    }  
      
      
    class ExtendsDemo   
    {  
        public static void main(String[] args)   
        {  
            Student s = new Student();  
            s.name = "zhagnsan";  
        }  
    }  
super关键字

super关键字和this关键字的用法类似
this代表本类对象的引用------本类中调用另一个重载构造方法用this(参数列表)
super代表父类对象的引用-------子类构造方法调用父类构造方法用super(参数列表)
当子父类出现同名成员时,可以用super进行区分
子类要调用父类构造函数时 ,可以使用super语句

子父类中变量的特点

类中的成员:变量、构造函数和函数

变量

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量用this,子类要访问父类中的同名变量用super

this代表本类对象的引用,super代表父类对象的引用

构造函数

子类的初始化过程中,首先回去执行父类的初始化动作。因为子类的构造方法中默认有一个super()。子类要使用父类的成员变量,这个初始化,必须在子类初始化之前完成。所以,子类的初始化过程中,会先执行父类的初始化。
如果父类没有无参构造方法。

子类访问父类的构造函数的原因

父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问父类中的构造函数。
使用super调用父类的带参构造。
使用this调用本身的其他构造。

    /* 
    子父类出现后,类成员的特点: 
     
    类中成员: 
    1,变量。 
    2,函数。 
    3,构造函数。 
     
    1,变量 
    如果子类中出现非私有的同名成员变量时, 
    子类要访问本类中的变量,用this 
    子类要访问父类中的同名变量,用super。 
     
    super的使用和this的使用几乎一致。 
    this代表的是本类对象的引用。 
    super代表的是父类对象的引用。 
     
    */  
      
    class Fu   
    {  
        private int num = 4;  
        public void setNum(int num)  
        {  
            this.num =num;  
        }  
        public int getNum()  
        {  
            return this.num;  
        }  
    }  
      
    class Zi extends Fu  
    {  
        //int num = 5;  
        void show()  
        {  
            System.out.println(num);  
        }  
    }  
      
    class  ExtendsDemo2  
    {  
        public static void main(String[] args)   
        {  
            Zi z = new Zi();  
            z.show();  
            //System.out.println(z.num+"...."+z.num);  
        }  
    }  

函数覆盖

当子类出现会和父类中一模一样的函数时,当子类调用该函数时,会运行子类函数的内容,如同父类中的函数被覆盖一样,这种是函数的另一种特性重写(覆盖)。

当子类继承了父类,沿袭了父类的功能到子类中,但是功能的内容却和父类不一致,这时候没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。

覆盖注意事项:
覆盖时,子类方法权限一定要大于等于父类方法权限;
静态只能覆盖静态。

子类可以调用父类中的非私有方法来间接访问父类的私有成员。
Person类中有私有字段name,Student继承Person
new Sudent().name; ×
new Student().getName(); √

覆盖的使用场景:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。

/* 
子父类中的函数。 
 
当子类出现和父类一模一样的函数时, 
当子类对象调用该函数,会运行子类函数的内容。 
如同父类的函数被覆盖一样。 
 
这种情况是函数的另一个特性:重写(覆盖) 
 
 
当子类继承父类,沿袭了父类的功能,到子类中, 
但是子类虽具备该功能,但是功能的内容却和父类不一致, 
这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。 
 
 
覆盖: 
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。 
 
2,静态只能覆盖静态。 
 
 
记住大家: 
重载:只看同名函数的参数列表。 
重写:子父类方法要一模一样。 
*/  
  
class Fu  
{  
    void show()  
    {  
        System.out.println("fu show");  
    }  
    void speak()  
    {  
        System.out.println("vb");  
    }  
}  
  
class Zi extends Fu  
{  
    void speak()  
    {  
        System.out.println("java");  
    }  
    void show()  
    {  
        System.out.println("zi show");  
    }  
}  
  
  
class ExtendsDemo3   
{  
    public static void main(String[] args)   
    {  
        Zi z = new Zi();  
        z.speak();  
  
    }  
}  
  
  
class Tel  
{  
    void show()  
    {  
        System.out.println("number");  
    }  
      
}  
  
class NewTel extends Tel  
{  
    void show()  
    {  
        //System.out.println("number");  
        super.show();  
        System.out.println("name");  
        System.out.println("pic");  
    }  
}
子父类中的构造函数(子类的实例化过程)
子类的所有构造函数默认都会访问父类中空参数的构造函数
因为每一个构造函数的第一行都有一条默认的语句super();
子类会具备父类的数据,所以要先明确父类是如何对这些数据初始化的
当父类中没有空参数构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数

    /* 
    子父类中的构造函数。 
     
    在对子类对象进行初始化时,父类的构造函数也会运行, 
    那是因为子类的构造函数默认第一行有一条隐式的语句 super(); 
    super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super(); 
     
    为什么子类一定要访问父类中的构造函数。 
     
    因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。 
    所以子类在对象初始化时,要先访问一下父类中的构造函数。 
    如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。 
     
    注意:super语句一定定义在子类构造函数的第一行。 
     
     
     
    子类的实例化过程。 
     
    结论: 
    子类的所有的构造函数,默认都会访问父类中空参数的构造函数。 
    因为子类每一个构造函数内的第一行都有一句隐式super(); 
     
    当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。 
     
    当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。 
    子类中至少会有一个构造函数会访问父类中的构造函数。 
    */  
    class Fu //extends Object  
    {  
        int num ;  
        Fu()  
        {  
            //super();  
            num= 60;  
            System.out.println("fu run");  
        }  
        Fu(int  x)  
        {  
            System.out.println("fu ...."+x);  
        }  
          
    }  
      
    class Zi extends Fu  
    {  
        Zi()  
        {  
              
            super();    
            //super(4);  
            System.out.println("zi run");  
        }  
        Zi(int x)  
        {  
            this();  
            //super();  
            //super(3);  
            System.out.println("zi..."+x);  
        }  
    }  
      
    class  ExtendsDemo4  
    {  
        public static void main(String[] args)   
        {  
            Zi z = new Zi(0);  
            System.out.println(z.num);  
        }  
    }  
      
    /* 
    class Person 
    { 
        private  String name; 
        Person(String name) 
        { 
            this.name = name; 
        } 
     
        void show(){} 
    } 
    class Student extends Person 
    { 
        Student(String name) 
        { 
            super(name); 
        } 
        void method() 
        { 
            super.show(); 
        } 
    } 
    */  

方法重写和重载有什么区别?

方法的重写用在子类方法与父类方法一模一样时,除权限修饰符,返回值类型,方法名和参数列表都是相同的。
重载用在同一个类中各方法方法名相同,参数列表不同(与返回值类型没有关系)的情况。
静态代码块、构造代码块,构造方法的执行顺序:
父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值