Java复习笔记-10

权限修饰符练习

创建a包,在a包中创建A类,提供方法

public class A {
    protected void m(){

    }
}

创建b包,在b包中创建B类,B类继承A类

public class B extends A {
}

在b包中再创建C类,提供main方法

public class C {
    public static void main(String[] args) {
        B b = new B();
        /**
         * m方法是使用protected修饰的
         * 所以使用范围是本类中,子类中和同包类中
         * m方法目前不在A类这个本类中用
         * m方法目前没有在子类B中调用,因为现在在C类中
         * m方法目前在同包类中吗? 不在
         */
//         b.m();
    }
}

在b包中创建D类,继承A类,提供main方法

public class D  extends A {
    public static void main(String[] args) {
        B b = new B();
        b.m();
    }
}

1 static

static是java中的关键字,可以修饰数据方法代码块,内部类

1.1 静态变量

static 修饰的数据称之为静态变量,或者叫类变量。静态变量是随着类的加载而加载到方法区,在方法区中被赋予了默认值。静态变量是先于对象而存在的,可以通过类名来调用。该类产生的所有的对象共用的是同一个静态变量。

每一个对象存储的都是该静态变量的地址。

使用格式: 类名.静态变量

类是加载到方法区的

类只加载一次

类会在首次使用时加载到方法区

静态变量的使用


public class TestDemo {
    public static void main(String[] args) {
        Person person1 = new Person();
        person1.name = "李小龙";
        person1.age = 31;
//        person1.kongfu = "截拳道";
        Person.kongfu = "截拳道";

        Person person2 = new Person();
        person2.name = "叶问";
        person2.age = 40;
//        person2.kongfu = "咏春";
        Person.kongfu = "咏春";

        // 静态变量在多个对象之间是共享的,是属于类的,而不是属于对象的
        // 静态变量可以使用  类名.静态变量名 来调用
        System.out.println(person1);
        System.out.println(person2);
    }
}


class Person{
    // 姓名
    String name;
    // 年龄
    int age;
    // 功夫
    static String kongfu;// 静态变量

    public String toString(){
        return name + "\t" + age + "\t" + kongfu;
    }

}

静态变量的内存图

在这里插入图片描述

思考:

静态变量能不能定义在构造方法中?

不能。静态变量在类加载
的时候加载并且初始化,构造方法在创建对象的时候执行。静态变量是存储在方法区,构造方法在栈内存中执行,创建的对象在堆内存中。

静态变量能不能定义在成员方法中?

不能,道理同上。

1.2 静态方法

static 修饰的方法称之为静态方法。静态方法在类加载时加载到方法区,并没有执行只是存储在方法区。在方法被调用的时候去栈内存中执行。静态方法本身也是先与对象而存在。习惯上是通过类名来调用静态方法。

格式: 类名.静态方法名();

静态方法一般用在工具类中。

public class SmsUtil {
    public static void sendSms(){
        System.out.println("发送短信...");
    }
}

// 调用方式
SmsUtil.sendSms();

思考:

静态方法中能使用this/super吗? 不能

静态方法中能够使用本类中的非静态方法? 不能。

静态方法能否被继承? 能

public class TestDemo3 {
    public static void main(String[] args) {
        // 向上转型
        Student.eat();
    }
}


class People{
    public static  void eat(){
        System.out.println("人要吃饭");
    }
}

class Student extends People{
}

静态方法能够被重写? 不能

父子类中可以存在方法签名一直的静态方法,称之为隐藏(hide)。

隐藏也适用于重写的五个原则

public class TestDemo3 {
    public static void main(String[] args) {
        // 向上转型
        People people = new Student();
        people.eat();
    }
}


class People{
    public static  void eat(){
        System.out.println("人要吃饭");
    }
}

class Student extends People{
    public static  void eat(){
        System.out.println("学生要吃饭");
    }
}

练习:定义一个类,统计这个类所创建对象的个数。

public class Demo {

    static int i = 0;


    {
        i++;
    }
 }

1.3 静态代码块

  • 静态代码块就是使用static修饰的代码块,只在类加载的时候执行一次
class Person {
    static  {
        // 静态代码块  是在类加载的时候执行一次
        System.out.println("静态代码块执行了");
    }
}
  • 只要使用到了类,这个类的静态代码块就会被调用(无论是创建对象还是调用静态方法或者调用静态变量)
        new Person();
        Person.i = 10;
        Person.method();

面试题:静态代码块、构造代码块、构造方法的执行顺序问题

  • 第一种情况
public class demo3 {
    public static void main(String[] args) {
        // 创建子类
        // 当要创建SB对象时,需要先加载SB这个类。
        // 加载SB类时,先要加载SB的父类SA。
        // SA加载时会调用它的静态代码块,所以第一个是A1
        // 再去加载SB类,会执行SB的静态代码块B1
        // 然后调用SB()方法,这个方法中有一个隐藏的super()
        // 这时又去调用父类的SA(),再调用SA()方法之前会先调用SA的构造代码块A2
        // 然后调用SA,打印A3
        // 然后SB()继续执行,但是发现有构造代码块,所以先执行SB的构造代码块B2
        // 最后SB()继续执行,打印B3
        new SB(); // A1 B1 A2 A3 B2 B3
    }
}
// 静态代码块、构造代码块、构造方法的执行顺序问题
class SA{
    static {
        // 静态代码块  类加载时执行一次
        System.out.println("A1");
    }

    {
        // 每次创建对象时,都会在构造方法之前执行
        System.out.println("A2");
    }

    public SA(){
        // 每次创建对象时执行
        System.out.println("A3");
    }
}

class SB extends SA{
    static {
        System.out.println("B1");
    }

    {
        System.out.println("B2");
    }

    public SB(){
        System.out.println("B3");
    }
}
  • 第二种情况
public class demo3 {
    public static void main(String[] args) {
        // 创建子类
        // 由于在加载SB类时需要创建一个静态变量SC,会先执行SC的构造方法,所以A1后面跟上C
        new SB();// A1 C B1 A2 A3 B2 B3
    }
}
// 静态代码块、构造代码块、构造方法的执行顺序问题
class SA{
    static {
        // 静态代码块  类加载时执行一次
        System.out.println("A1");
    }

    {
        // 每次创建对象时,都会在构造方法之前执行
        System.out.println("A2");
    }

    public SA(){
        // 每次创建对象时执行
        System.out.println("A3");
    }
}

class SB extends SA{
    static SC c = new SC();
    static {
        System.out.println("B1");
    }

    {
        System.out.println("B2");
    }

    public SB(){
        System.out.println("B3");
    }
}

class SC{
    public SC(){
        System.out.println("C");
    }
}

  • 第三种情况
public class demo3 {
    public static void main(String[] args) {
        // 创建子类
        // 由于SD只有声明,根本没有创建,所以构造方法不会执行
        new SB();// A1 C B1 A2 A3 B2 B3
    }
}
// 静态代码块、构造代码块、构造方法的执行顺序问题
class SA{
    SD d;
    static {
        // 静态代码块  类加载时执行一次
        System.out.println("A1");
    }

    {
        // 每次创建对象时,都会在构造方法之前执行
        System.out.println("A2");
    }

    public SA(){
        // 每次创建对象时执行
        System.out.println("A3");
    }
}

class SB extends SA{
    static SC c = new SC();
    static {
        System.out.println("B1");
    }

    {
        System.out.println("B2");
    }

    public SB(){
        System.out.println("B3");
    }
}

class SC{
    public SC(){
        System.out.println("C");
    }
}


class SD extends SC{
    public SD(){
        System.out.println("D");
    }
}

  • 第四种情况
public class demo3 {
    public static void main(String[] args) {
        // 创建子类
        // A2打印后,还需要创建SD。
//        由于SD是SC的子类,所以要先执行SC(),再执行SC()
        // 所以在A2后面添加了C D
        new SB();// A1 C B1 A2 C D A3 B2 B3
    }
}
// 静态代码块、构造代码块、构造方法的执行顺序问题
class SA{
    SD d;
    static {
        // 静态代码块  类加载时执行一次
        System.out.println("A1");
    }

    {
        // 每次创建对象时,都会在构造方法之前执行
        System.out.println("A2");
        d = new SD();
    }

    public SA(){
        // 每次创建对象时执行
        System.out.println("A3");
    }
}

class SB extends SA{
    static SC c = new SC();
    static {
        System.out.println("B1");
    }

    {
        System.out.println("B2");
    }

    public SB(){
        System.out.println("B3");
    }
}

class SC{
    public SC(){
        System.out.println("C");
    }
}


class SD extends SC{
    public SD(){
        System.out.println("D");
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值