Java架构-JavaSE(三)之static、final、abstract修饰符

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Coco_Wditm/article/details/84070199

阅读目录(Content)

一、static修饰符
  1.1、static变量
  1.2、static方法
1.3、代码块和静态代码块
1.4、创建和初始化对象的过程
二、final修饰符
2.1、修饰类
2.2、修饰方法
2.3、修饰变量
三、abstract修饰符
  3.1、抽象类和抽象方法的关系
  3.2、语法
  3.3、特点及作用
  3.4、思考
一、static修饰符
  1.1、static变量
在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

    静态变量和非静态变量的区别
        静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.

	 public class Student{
                private static int age;
                private double score;
                public static void main(String[] args) {
                    Student s = new Student();
                    //推荐使用类名访问静态成员
                    System.out.println(Student.age);
                    System.out.println(s.age);

                    System.out.println(s.score);
                }
            }

静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份,它们之间互不影响.
例如:

public class Student{
private static int count;
private int num;
public Student() {
count++;
num++;
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
Student s4 = new Student();
//因为还是在类中,所以可以直接访问私有属性
System.out.println(s1.num);
System.out.println(s2.num);
System.out.println(s3.num);
System.out.println(s4.num);

                System.out.println(Student.count);
                System.out.println(s1.count);
                System.out.println(s2.count);
                System.out.println(s3.count);
                System.out.println(s4.count);
            }
        }

在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存
所以静态变量可以使用类名来直接访问,而不需要使用对象来访问.

1.2、static方法
在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。

    静态方法和非静态方法的区别
        静态方法数属于类的,"可以"使用类名来调用,非静态方法是属于对象的,"必须"使用对象来调用.
    
    静态方法"不可以"直接访问类中的非静态变量和非静态方法,但是"可以"直接访问类中的静态变量和静态方法
        注意:this和super在类中属于非静态的变量.(静态方法中不能使用)
        例如:    
         public class Student{
            private static int count;
            private int num;
            public void run(){}
            public static void go(){}
            

            public static void test(){
                //编译通过
                System.out.println(count);
                go();
                
                //编译报错
                System.out.println(num);
                run();
            }

        }

非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方法
例如:

         public class Student{
            private static int count;
            private int num;
            public void run(){}
            public static void go(){}

            public void test(){
                //编译通过
                System.out.println(count);
                go();
                
                //编译通过
                System.out.println(num);
                run();
            }

        }
    思考:为什么静态方法和非静态方法不能直接相互访问?
            
    父类的静态方法可以被子类继承,但是不能被子类重写
        例如:
        
        public class Person {
                 public static void method() {}
            }
            
            //编译报错
            public class Student extends Person {
                 public void method(){}
            }


        例如:
            public class Person {
                 public static void test() {
                    System.out.println("Person");
                 }
            }
            
            //编译通过,但不是重写
            public class Student extends Person {
                 public static void test(){
                    System.out.println("Student");
                 }
            }
            main:
                Perosn p = new Student();
                p.test();//输出Person
                p = new Person();
                p.test();//输出Perosn

            和非静态方法重写后的效果不一样
           
    父类的非静态方法不能被子类重写为静态方法    
        例如:

            public class Person {
                 public void test() {
                    System.out.println("Person");
                 }
            }
            
            //编译报错
            public class Student extends Person {
                 public static void test(){
                    System.out.println("Student");
                 }
            }

1.3、代码块和静态代码块
1)类中可以编写代码块和静态代码块
例如:
public class Person {
{
//代码块(匿名代码块)
}

            static{
                //静态代码块
            }
        }
    
    2)匿名代码块和静态代码块的执行
        因为没有名字,在程序并不能主动调用这些代码块。

        匿名代码块是在创建对象的时候自动执行的,并且在构造器执行之前。同时匿名代码块在每次创建对象的时候都会自动执行.

        静态代码块是在类加载完成之后就自动执行,并且只执行一次.

        注:每个类在第一次被使用的时候就会被加载,并且一般只会加载一次.

        例如:
   	     public class Person {
              {
                    System.out.println("匿名代码块");
                 }

               static{
                     System.out.println("静态代码块");
                 }
                 public Person(){
                   System.out.println("构造器");
                 }
            }
             main:
                Student s1 = new Student();
                Student s2 = new Student();
                 Student s3 = new Student();


                //输出结果:
                静态代码块
                匿名代码块
                构造器
                匿名代码块
                构造器
                匿名代码块
                构造器

    3)匿名代码块和静态代码块的作用
        匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。

        静态代码块的作用是给类中的静态成员变量初始化赋值。
        例如:

![public class Person {
public static String name;
static{
name = “tom”;
}
public Person(){
name = “zs”;
}
}
main:
System.out.println(Person.name);//tom]

            注:在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静态变量可以不创建对象而直接使用类名来访问.          

1.4、创建和初始化对象的过程

     Student s = new Student();
        4.1)Student类之前没有进行类加载
            1、类加载,同时初始化类中静态的属性
            2、执行静态代码块
            3、分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
            4、调用Student的父类构造器
            5、对Student中的属性进行显示赋值(如果有的话)
            6、执行匿名代码块
            7、执行构造器
            8、返回内存地址

            注:子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

例如:
在这里插入图片描述

            //输出结果:
            Student静态代码块
            Person构造器
            student print方法: name = null
            Student匿名代码块
            Student构造器


        Student s = new Student();
       4. 2)Student类之前已经进行了类加载
            1.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
            2.调用Student的父类构造器
            3.对Student中的属性进行显示赋值(如果有的话)
            4.执行匿名代码块
            5.执行构造器
            6.返回内存地址

5)静态导入
    静态导入是JDK5.0引入的新特性。

例如:
在这里插入图片描述

二、final修饰符
2.1、修饰类
用final修饰的类不能被继承,没有子类。
例如:我们是无法写一个类去继承String类,然后对String类型扩展的,因为API中已经被String类定义为final的了.
我们也可以定义final修饰的类:
在这里插入图片描述
2.2、修饰方法
用final修饰的方法可以被继承,但是不能被子类的重写。
例如:每个类都是Object类的子类,继承了Object中的众多方法,在子类中可以重写toString方法、equals方法等,但是不能重写getClass方法 wait方法等,因为这些方法都是使用fianl修饰的。

    我们也可以定义final修饰的方法:     

在这里插入图片描述
2.3、修饰变量
用final修饰的变量表示常量,只能被赋一次值.其实使用final修饰的变量也就成了常量了,因为值不会再变了。

    1)修饰局部变量:
    例如:

在这里插入图片描述

2)修饰成员变量:
        非静态成员变量:
            public class Person{
                private final int a;
            }
            只有一次机会,可以给此变量a赋值的位置:
                声明的同时赋值
                匿名代码块中赋值
                构造器中赋值(类中出现的所有构造器都要写)
            
        静态成员变量:
            public class Person{
                private static final int a;
            }
            只有一次机会,可以给此变量a赋值的位置:
                声明的同时赋值
                静态代码块中赋值
        
3)修饰引用变量 

在这里插入图片描述

三、abstract修饰符
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

3.1、抽象类和抽象方法的关系
   抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

3.2、语法
    public abstract class Action{
   public abstract void doSomething();
   }

      public void doSomething(){...}
      对于这个普通方法来讲:
      "public void doSomething()"这部分是方法的声明
      "{...}"这部分是方法的实现,如果大括号中什么都没写,就叫方法的空实现

      声明类的同时,加上abstract修饰符就是抽象类
      声明方法的时候,加上abstract修饰符,并且去掉方法的大口号,同时结尾加上分号,该方法就是抽象方法。

3.3、特点及作用
     抽象类,不能使用new关键在来创建对象,它是用来让子类继承的。
  抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

      注:子类继承抽象类后,需要实现抽象类中没有实现的抽象方法,否则这个子类也要声明为抽象类。
      例如:
          public abstract class Action{
              public abstract void doSomething();
          }
          main:
              //编译报错,抽象类不能new对象
              Action a = new Action();
        
          //子类继承抽象类
          public class Eat extends Action{
              //实现父类中没有实现的抽象方法
              public void doSomething(){
                  //code
              }
          }

          main:
              Action a = new Eat();
              a.doSomething();
           
          注:子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

3.4、思考
    思考1:抽象类不能new对象,那么抽象类中有没有构造器?
    思考2:抽象类和抽象方法意义(为什么要编写抽象类、抽象方法)
     有抽象方法的抽象类
     无抽象方法的抽象类
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!
合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

还是那句话,希望此文能帮到大家的同时,也听听大家的观点。欢迎留言讨论,加关注,分享你的高见!持续更新!

To-陌霖Java架构

分享互联网最新文章 关注互联网最新发展

猜你喜欢

转载自blog.csdn.net/Coco_Wditm/article/details/84070199