关于Abstract,static,final的理解

Abstract,static,final理解

一 . Abstract 抽象

1> 修饰类

  • 一个类被Abstract修饰之后,就不能new对象了,修饰父类
  • 被Abstract修饰的说明是一个不是一个具体的类型,是一个类别,是一个父类,不应该被具体化
  • 说明这个类不完整,不够具体,抽象类无法独立存在
  • 为子类输出共性
作用:
    1> 可以被子类继承,提供共性属性和方法
    2> 可声明为引用,强制使用多态
    3> 抽象父类可以是子类的组成部分,依附于子类对象的存在
    4> 由父类共性+子类独有组成完整的子类对象
    5> 抽象类也是有构造方法的,可以由子类来调用,构建子类对象时调用父类构造方法
    6> 和普通类的区别,就是不能new,其他和普通的类都一样

2> 修饰方法

  • 抽象方法:只有声明,没有实现,不够完整
  • 方法的声明时必要的,可是发放的实现是多余的,因为父类的方法的实现是无法满足子类的需求的,最后子类都会进行重写
  • 含有抽象方法的类必须是个抽象类
  • 抽象类中不一定有抽象方法
  • 子类必须重写父类的所有的抽象方法
//如果父类是个抽象
//那么子类必须重写父类的所有的抽象方法
//抽象类中不一定有抽象方法
abstract class Animal{//含有不完整的方法,那么这个类也是不完整的
    String bread;
    int age;

    public Animal(){
        System.out.println("这是抽象类的无参构造函数..");
    }

    //这是一个抽象方法
    //含有抽象方法的类必须是个抽象类
    public abstract void eat();//只有声明,没有实现,意为不完整

    //还可以拥有普通的方法
    public  void slep(){};
}

//一个抽象类的子类
class Dog extends Animal{

    //必须重写父类所有的抽象方法
    public void eat(){

    }

}

//子类不想实现父类的抽象方法
//那么这个类也必须是个抽象类
//同时继承父类所有的未实现的抽象方法
abstract class Cat extends Animal{

}

二 . static 静态

类加载时.在方法区中,会存放一个有MyClass对象的类信息,MyClass.class

  • 普通的实例变量是在创建对象的时候在内存中创建对象
  • 静态方法是在类加载时就在内存中创建对象
  • 静态方法允许直接访问静态成员
  • 静态方法不能直接访问非静态成员
  • 静态方法中不允许使用this和super关键字
  • 静态方法可以继承,不能重写,没有多态
    • 动态方法要到运行时才是可以明确执行的是哪个,因为不能确定是否有子类将他重写覆盖了
    • 静态方法不用到运行时,编译时就会知道了.运行时不可变

    java中方法的调用分为两种

    ? 1> 静态分派: 静态方法中,允许参数列表不同的重名方法,指静态方法之间的重载

    ? 2> 动态分派: 在具有继承关系的情况下,调用实例方法时,自低向上(先查子类,再找父类,一直向上查找)查找可 用的方法版本,指实例方法的覆盖

    jvm方法调用的指令:

    ? 1> invokespacial 调用私有方法和构造方法

    ? 2> invokeinteface 调用接口方法

    ? 3> invokestatic 调用静态方法

    ? 4> invokevirtual 调用虚方法(父类定义的,日后被子类覆盖的方法)

    ? 5> invokedynamic 调用动态链接方法

    public class TestStatic{
        public static void main(String[] args){
    
            A.staticMethod();
            B.staticMethod();//继承了父类的静态方法,但是不能重写,所以不存在多态
    
            A a = new B();
    
            //也是可以掉调用的,即使在子类中也有一个同样的静态方法
            //下面的方法调用的依然是父类中的静态方法
            //因为静态方法不能被覆盖
            a.staticMethod();
    
        }
    }
    
    class A{
    
        static int find;
        public static void staticMethod(){
            System.out.println("----" + find);
        }
    }
    
    class B extends A{
    
        //假如B中也存在一个,也是不行的,不能覆盖
        public static void staticMethod(){
            System.out.println("----" + find);
        }
    }

1> 静态属性(类属性)

  • 静态成员是全类所有对象共享的成员
  • 在全类中只有一份,不因创建多个对象而产生多份
  • 不必创建对象,可以直接通过类名访问
a .普通的属性
public class TestStatic{
    public static void main(String[] args){
        MyClass mc1 = new MyClass();
        m1.a = 10;

        //每个对象都拥有自己单独的a
        //每个对象都在堆中用一个自己的a空间,指向栈中的mc2引用
        MyClass mc2 = new MyClass();
        m2.a = 20;

        System.out.println(m1.a + "--" + m2.a);//输出结果: 10  --  20

    }
}

class MyClass{
    //每个对象都持有一例
    int a; //实例属性
}
b.静态属性
public class TestStatic{
    public static void main(String[] args){

        //m1.b和m2.b访问的都是方法区中的b,是同一个
        //每个类的实例都是使用的这一个b
        MyClass mc1 = new MyClass();
        MyClass mc2 = new MyClass();

        m1.a = 10;
        m2.a = 20;

        m1.b = 100;
        m2.b = 202;//覆盖了前面的m1赋值的100//自动转换 m2.b --> MyClass.b

        //不用通过对象名访问静态属性
        //直接使用类名访问
        MyClass.b = 200;

        System.out.println(m1.a + "--" + m2.a);//输出结果: 10  --  20
        System.out.println(m1.b + "--" + m2.b);//输出结果: 200  --  200

    }
}

class MyClass{

    //实例属性
    int a;

    //在这个类加载的时候,这个static属性就放到方法区了    //整个类的共享的.只有单独的一份
    static int b; //静态属性
}

2> 静态方法

class Student{

    //静态方法
    //类的所有对象公用
    public static void method(){

    }

    public void fan(){
        //同一个类的其他方法使用本类的静态方法,直接使用方法名
        method();
    }

}

class Test{
     public static void main(String[] args){
        //类外使用静态方法
         //类名.方法名
         Student.method();
     }
}

3> static高级应用

1-类加载
  • JVM 首次使用某个类的时候,是需要通过CLASSPATH查找该需要使用类的.class文件
  • 将.class文件中对类的描述信息加载到内存中,进行保存(比如:包名,类名,属性,方法,构造方法等信息)
  • 加载的时机
    • 创建对象
    • 创建子类对象
    • 访问静态属性
    • 调用静态方法
    • Class.forName("全限定名") :(主动加载一个类,但是不接收返回值,只是加载到内存中,目前并不使用)
class TestClassLoaded{
    public static void main(String[] args){
        new Super();//首次用到,创建了一个类的对象,就需要加载这个类

        Super.sMethod();//或者这个类中有静态方法,那么在首次调用这个静态方法的时候,也会加载这个类
        Super.sname;//同上

        Sub.sMethod();//调用父类的静态方法,首次使用也会加载super类,

    }

}

class Super{

    String name;

    static String sname;//静态属性

    //静态方法
    public static void sMethod(
        {

        }
}

class Sub extends Super{

}
2-静态代码块
  • 静态代码块是由类加载触发的(仅一次)
  • 可为静态属性赋值,或者必要的初始行为
  • 首先加载执行静态属性和静态代码块
  • 再来加载普通属性和动态代码块和构造方法
public class Test{
    public static void main(String[] args){

        //静态代码块是由类加载触发的

        new MyClass;

        System.out.print(MyClass.sname);//这两个都会执行静态代码块

    }
}

class MyClass{

    //静态属性
    static int sname = 88;

    int name = 99;

    //静态代码块
    static{
        System.out.print("这诗集静态代码块中得到输出");

        //使用了静态的属性
        //执行静态代码块和静态属性的时候,根据书写顺序加载
        //如这里使用了sname静态属性,那么这个属性必须定义到静态代码块前面
        System.out.print(sname);
        }

    MyClass{
        System.out.print("类中音译的属性值为: " + name);
        System.out.print("这是构造方法中得到输出");
    }

    public void m1(){
        int a = 10;
    }
}
3- 各个模块之间的执行顺序
package com.huqi.demo1;

public class TestLoadSort{
    public static void main(String[] args) throws Exception{

        //new Super();
        new Sub();//创建一个子类的对象,查看加载各个属性和代码块的顺序

        //主动加载一个类,只执行静态代码的部分
        Class.forName("com.huqi.demo1.Sub");//里面的必须带包名
        /*
        如果只执行这一行代码,则会输出下面的语句,这个是类级别的,从这里下面的代码都是对象级别的
            这是父类的静态方法---
            这是父类的静态代码块---
            这是子类的静态方法---
            是子类的静态代码块---
        */

    }
}

class Super{

    static String staticField = "这是父类的静态方法---";

    static{
        System.out.println(staticField);
        System.out.println("这是父类的静态代码块---");
    }

    String instanceField = "这是父类的成员属性---";

    {
        System.out.println(instanceField);
        System.out.println("这是父类的动态代码块---");
    }

    public Super(){
        System.out.println("这是父类的构造方法---");
    }

}

class Sub extends Super{

    static String staticField2 = "这是子类的静态方法---";

    static{
        System.out.println(staticField2);
        System.out.println("这是子类的静态代码块---");
    }

    String instanceField2 = "这是子类的成员属性---";

    {
        System.out.println(instanceField2);
        System.out.println("这是子类的动态代码块---");
    }

    public Sub(){
        System.out.println("这是子类的构造方法---");
    }
}
当new Sub时的结果
    这是父类的静态方法---
    这是父类的静态代码块---
    这是子类的静态方法---
    这是子类的静态代码块---   //从这里分割,前面的是类几级别的,类加载时运行,后面的都是创建对象时执行
    这是父类的成员属性---
    这是父类的动态代码块---
    这是父类的构造方法---
    这是子类的成员属性---
    这是子类的动态代码块---
    这是子类的构造方法---

当new Super时的结果:
    这是父类的静态方法---
    这是父类的静态代码块---
    这是父类的成员属性---
    这是父类的动态代码块---
    这是父类的构造方法---

三.final

  • final修饰类: 此类不能被继承
  • final修饰方法: 此方法不能被覆盖
  • final修饰变量:此变量值不能被改变(无初始值.只允许赋值一次)
    • 局部变量 :显示初始化
    • 实例变量: 显示初始化,动态代码块,构造方法
    • 静态常量: 显示初始化,静态代码块
    • 基本数据类型常量:值不可改变
    • 应用数据类型常量: 地址不可变

1> final类

  • final修饰类: 此类不能被继承.

    • String.math.System均为final修饰的类,不能被继承
  • final修饰的方法不能被覆盖
public class testFinal{

}

//final不能和abstract一起使用,是冲突的两个
final class Super{

}
//发生错误,不能继承被final修饰的类
final Sub extends Super{

}

2> final变量

  • final修饰变量,就变成了常量
  • 用final修饰的属性没有默认值
  • 只能赋一次值
public class testFinal{
    main(){
        //用final修饰的是常量
        //先赋值再使用
        final double PI = 3.1415;
    }
}

//final不能和abstract一起使用,是冲突的两个
final class Super{

    //没有默认值,必须要初始化
    //在对象初始化完成之前完成初始化的操作
    final int field = 10;

    final int FIELD;

    public Super(){
        //对常量进行初始化
        FIELD = 20;
    }

    //静态常量
    final static void STATIC_FIELD = 20;

    static{
        //可以给STATIC_FIELD赋值
        //STATIC_FIELD = 20;
    }

}

原文地址:https://www.cnblogs.com/huqisue/p/12384896.html

时间: 2024-12-28 20:33:55

关于Abstract,static,final的理解的相关文章

为什么构造器不能是abstract, static, final, native or synchronized的?

Unlike methods, a constructor cannot be abstract, static, final, native  or synchronized. 1. A constructor is not inherited, so there is no need to declare it final 2. As the same reason above, an abstract constructor could never be implemented. 3. A

Java修饰符abstract,static,final的区别

注意:有抽象方法的类一定是抽象类.但是抽象类中不一定都是抽象方法,也可以全是具体方法.abstract修饰符在修饰类时必须放在类名前. abstract修饰方法就是要求其子类覆盖(实现)这个方法.调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其子类中实现,除非子类本身也是抽象类. 注意:父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能力,否则子类也必须是抽象类.抽象类中可以有构造方法,是子类在构造子类对

Java修饰符 abstract,static,final 的区别详解

一:static 表示静态,它可以修饰属性,方法和代码块. 1.static修饰属性(类变量),那么这个属性就可以用类名.属性名来访问,也就是使这个属性成为本类的类变量,为本类对象所共有.这个属性就是全类公有.(共有的类变量与对象无关,只和类有关). 类加载的过程,类本身也是保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程成为类的加载.JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件. 类变量

浅析java修饰符之public default protected private static final abstract

浅析java修饰符之public default protected private static final abstract 一   修饰符的作用:用来定义类.方法或者变量,通常放在语句的最前端 二   分类(大致分两类) 1.访问修饰符,包括:public default protected private 2.非访问修饰符,包括:static final abstract 三 访问修饰符--Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java支持4种不同的访问权

static final public synchronized abstract

1.static final public synchronized 可以混用 而且顺序不限 2.abstract 只能与public或protected连用,不能用default或private 也不能与static final  synchronized中的任意一个连用 原因: abstract要继承(多态) 但static的是编译期绑定,拒绝多态 synchronized没有继承性,父类加锁 子类默认不加锁 ,所以加了synchtonizd也没用 final本身就是阻止重写的

【Java关键字-Interface】为什么Interface中的变量只能是 public static final

三个关键字在接口中的存在原因:public:接口可以被其他接口继承,也可以被类实现,类与接口.接口与接口可能会形成多层级关系,采用public可以满足变量的访问范围: static:如果变量不是static的,那么接口必须实例化才可以访问自己的变量,接口不能被实例化,故非static的变量是无效的: final:如果变量不是final的,而方法是abstract的,因此接口中的方法又不可以修改变量值,虽然可以直接修改静态成员变量,但所有实现类对应的值都被修改了,此做法等同于抽象类,故需要fina

Java中static final 关键字释惑

static static表示"全局"或者"静态"的意思 1. 按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量:另一种是没有被static修饰的变量,叫实例变量.两者的区别是: 对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的). 对于实例变量,每创建一个实例,就会为实例变量分配一次内存

为什么接口要规定成员变量必须是public static final的呢?(转)

在interface里面的变量默认都是public static final 的.所以可以直接省略修饰符: String param="ssm"://变量需要初始化 为什么接口要规定成员变量必须是public static final的呢? 答: 首先接口是一种高度抽象的"模版",,而接口中的属性也就是’模版’的成员,就应当是所有实现"模版"的实现类的共有特性,所以它是public static的 ,是所有实现类共有的 .假如可以是非static

Java 关键字static final使用总结

Static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享.只要该类加载,JVM虚拟机就能根据类名在运行时数据区的方法区内找到他们.因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象.1.static修饰类的成员方法或者成员变量,我们通常称该方法是静态方法,该方法是静态变量:若用public修饰static成员方法或者成