Javase-OOP(高级)

 1、类变量和类方法

1.1 什么是类变量

类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。

1.2 定义类变量

//访问修饰符 static 数据类型 变量名;
public static String name = "小明";

 1.3 如何访问静态变量

//类名.静态变量名【静态变量的访问你修饰符的访问权限和范围和普通属性是一样的】
//静态变量是随着类的加载创建,所以即使没有new对象也能访问
Car.name;

1.4 类变量的使用细节

1. 什么时候使用静态变量

        当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用静态变量。

2. 类变量与实例变量区别

        类变量是该类的所有对象共享的,而实例变量是每个对象独享的。

3. 加上static称为类变量或者静态变量,否则称为实例变量/普通变量/非静态变量

4. 静态变量可以通过 类名.类变量名 或者 对象名.类变量名  来访问,推荐使用 类名.类变量名方式访问。【前提是:  满足访问修饰符的访问权限和范围】

5. 实例变量不能通过 类名.方法名 来访问。

6. 类变量是在类加载的时候就创建了,所以我们没有创建对象实例。ps:不用new对象

7. 静态变量的生命周期是随着类的加载开始,随着类消亡而销毁。

1.5 定义类方法

//访问你修饰符 static 数据返回类型 方法名(){}

//1.放方法使用了static修饰后,该方法就是静态方法//2.静态方法就可以访问静态属性/变量
public static String getAge(){  

}

1.6 类方法经典的使用场景

1. 当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。

//比如:工具类中的方法 utils、Math类、Arrays类、Collections集合类的源码


//直接MyTools.calSum(a,b);就能调用//不用new对象
class MyTools{
    public static double calSum(int a,int b){
        return a + b;
    }
}

1.7 类方法使用细节

1. 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区;类方法中无this的参数,普通方法中隐含着this的参数

2. 类方法可以通过类名调用,也可以通过对象名调用。

3. 普通方法和对象有关,需要通过对象名调用,比如 对象名.方法名(参数),不能通过类名调用。

4. 类方法中不允许使用和对象有关的关键字,比如this和super。

5. 普通方法可以。静态方法只能访问静态变量或者静态方法。

6. 普通方法成员,既可以访问非静态成员,也可以访问静态成员。

结论:

  1. 静态方法只能访问静态成员

  2. 非静态方法,可以访问所有的成员

  3. 在编写代码时,仍要遵守访问权限规则

2、代码块 

2.1 基本介绍

代码化块又称为初始化块,属于类中的成员[即是类的一部分], 类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。

但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。

2.2 基本语法 

//	[修饰符]{  代码  };


static{
    
};

说明注意:

1. 修饰符可选,要写的话只能写static

2. 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫做普通代码块/非静态代码块。

3. 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)

4. ;号可以写上,也可以省略

2.3 代码块的好处 

1. 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作

2. 场景:如果多个构造器种都有重复的语句,可以抽取到初始化代码块中,提高代码的复用性

class Movie{
    private String name;
    private double price;
    private String director;

    //这样不管当我们调用哪个构造器,都会先调用代码块种的内容
    //代码块的调用优先于构造器
    {
        System.out.println("电影屏幕打开。。。");
        System.out.println("广告开始。。。");
        System.out.println("电影开始。。。");
    }

    public Test(String name) {
        this.name = name;
    }

    public Test(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public Test(String name, double price, String director) {
        this.name = name;
        this.price = price;
        this.director = director;
    }
}

 2.4 代码块使用注意事项和细节

        1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并*只会执行一次。如果是普通代码块,每创建一个对象,就执行。

        2. 类什么时候加载【重要!】

//1. 创建对象实例时(new)

class AA{
    static{
        System.out.println("AA 的静态代码块1被执行。。")
    }
}


AA aa = new AA();
//new对象就会执行静态代码块的内容
//输出    AA 的静态代码块1被执行。。
//2.创建子类对象实例,父类也会被加载
class BB extends AA{
    System.out.println("BB 的静态代码块1被执行。。")
}


BB bb = new BB();
//继承的本质:先加载父类在加载子类
//所以:AA 的静态代码块1被执行。。  先输出!
//	   BB 的静态代码块1被执行。。  后输出!
//3.使用类的静态成员时(静态属性,静态方法)


class Cat{
    public static int n1 = 999;//静态属性
    static{
        System.out.println("Cat 的静态代码块1被执行。。。")
    }
}


Cat.n1;//n1是静态属性,本类的静态成员被调用,所以静态代码块也会被调用
//所以输出:Cat 的静态代码块1被执行。。。
//		  999
//如果有Cat继承了父类,那么父类的静态代码块也会被加载,也比Cat先加载

        3. 普通代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会被调用一次。

如果只是使用类的静态成员,普通代码块不会执行。

class AA{
    public static int a = 1;
    //静态代码块
    static{
        System.out.println("AA 的静态代码块1被执行。。");
    }
    //普通代码块
    {
       System.out.println("AA 的普通代码块1被执行。。"); 
    }
}

System.out.println(AA.a);
//这样调用只会执行静态代码块,不会执行普通代码块,因为没有new对象,
//普通代码块只会在创建对象实例化的时候才会被调用。而且时没创建一次就调用一次!
//在类加载的时候不会被调用!
//所以这里输出:AA 的静态代码块1被执行。。

        4. 总结

1. static代码块时类加载时执行的,类只加载一次,所以static代码块只执行一次

2. 普通代码块是在创建对象时调用的,创建一次,调用一次。

        5.  创建对象时,在一个类调用顺序是:(难点、重点)


/**
*1. 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,
*如果有多个静态代码块和多个静态变量初始化时,按照他们定义的顺序调用)
*
*
**/

class A{
    //静态属性初始化
    private static int n1 = getN1();
    //静态代码块
    static{
        System.out.println("A 静态代码块01");
    }
    public static int getN1(){
        Sysyem.out.println("getN1被调用");
        return 100;
    }
}


A a = new A();
//先输出 getN1()被调用
//在输出 A 静态代码块01
//原因:getN1先初始化,static后初始化。如果有多个静态成员按照他们定义的顺序调用。

/**
*2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,
*如果多个普通代码块和多个普通属性初始化,则按定义顺序调用)
**/

class A{
    //静态属性初始化
    private static int n1 = getN1();
    private int n2 = getN2();
    //静态代码块
    static{
        System.out.println("A 静态代码块01");
    }
    //普通代码块
    {
        System.out.println("A 普通码块02");
    }
    //静态方法
    public static int getN1(){
        Sysyem.out.println("静态方法getN1被调用");
        return 100;
    }
    
    //普通方法
    public  int getN2(){
        Sysyem.out.println("普通方法getN2被调用");
        return 200;
    }
    //无参构造器
    public void A(){
        Sysyem.out.println("无参构造器被调用了!");
}

A a = new A();
/*
输出顺序:1.静态方法getN1被调用
		2.A 静态代码块01
		3.普通方法getN2被调用
		4.A 普通码块02
		5.无参构造器被调用了
*/
//3. 调用构造器

创建对象时,一个类调用顺序是:

1. 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化时,按照他们定义的顺序调用)

2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果多个普通代码块和多个普通属性初始化,则按定义顺序调用)

3. 调用构造方法

         6. 构造方法的最前面其实隐含了super()和调用普通代码块。

class A {
    //构造器
    public A(){
        //这里有隐藏得执行要求
        // 1.super();
        // 2.调用普通代码块
        System.out.println("it is ok");
    }
}

        7. 有继承关系的两个类:

public class Test {
    public static void main(String[] args) {
        /*
            1. 进行类的加载
                1.1 先加载父类 A 1.2 在加载 B
            2. 创建对象
                2.1 从子类的构造器开始
         */
        new B();
    }
}
class A {
    private static int n1 = getValue01();
    static {
        System.out.println("A的一个静态代码块");
    }
    {
        System.out.println("A的一个普通代码块");
    }
    public int n2 = getValue02();
    public static int getValue01(){
        System.out.println("getValue01");
        return 10;
    }
    public int getValue02(){
        System.out.println("getValue02");
        return 10;
    }

    public A(){
        System.out.println("A的构造器");
    }
}
class B extends A{
    private static int n3 = getValue03();
    static {
        System.out.println("B的一个静态方法");
    }
    {
        System.out.println("B的一个普通代码块");
    }
    public int n4 = getValue04();
    public static int getValue03(){
        System.out.println("getValue03");
        return 10;
    }
    public int getValue04(){
        System.out.println("getValue04");
        return 10;
    }
    public B(){
        //隐藏了super();
        //普通代码块
        //普通属性的初始化。。。
        System.out.println("B的构造器");
    }

}

/*
输出顺序:
	getValue01
A的一个静态代码块
getValue03
B的一个静态方法
A的一个普通代码块
getValue02
A的构造器
B的一个普通代码块
getValue04
B的构造器
*/

得出结论输出顺序:

1. 父类的静态代码块和静态方法(按照编写的顺序来)
2. 子类的静态代码块和静态方法(按照编写的顺序来)
3. 父类的普通代码块、普通方法(按照编写的顺序来)
4. 父类的构造方法
5. 子类的普通代码块、普通方法(按照编写的顺序来)
6. 子类的构造方法

        8.  静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值