java面向对象 final && static 关键字

2023-11-19

目录

关键字:static

类属性、类方法的设计思想

类变量(class Variable)

静态变量的内存解析

类方法(class method)  

单例 (Singleton)设计模式

理解main方法的语法

代码块

关键字:final

总结


关键字:static

当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中 都单独分配一个用于代表国家名称的变量

 

class Circle{
private double radius;
public Circle(double radius){this.radius=radius;}
public double findArea(){return Math.PI*radius*radius;}}
创建两个 Circle 对象
Circle c1=new Circle(2.0);
//c1.radius=2.0
Circle c2=new Circle(3.0);
//c2.radius=3.0
Circle 类中的变量 radius 是一个 实例变量 (instance variable) ,它属于类的每一个对象,不能被同一个类的不同对象所共享。
上例中 c1 radius 独立于 c2 radius ,存储在不同的空间。 c1 中的 radius 变化不会影响c2 radius ,反之亦然。
如果想让一个类的所有实例共享数据,就用类变量!

类属性、类方法的设计思想

类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些属性不因对象的不同而改变,将这些属性设置为类属性。相应 的方法设置为类方法。

如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。

使用范围: 在Java 类中,可用 static 修饰 属性、方法 代码块、内部类
修饰后的成员具备以下特点
  • 随着类的加载而加载
  • 优先于对象存在
  • 修饰的成员,被所有对象所共享
  • 访问权限允许时,可不创建对象,直接被类调用

类变量(class Variable)

类变量(类属性)由该类的所有实例共享

 

public class Person {
    private int id;
    public static int total = 0;
    public Person() {
    total++;
    id = total;
    }
}
public static void main(String args[]){
    Person Tom=new Person();
    Tom.id=0;
    total=100; // 不用创建对象就可以访问静态成员
    }
}
public class StaticDemo {
    public static void main(String args[]) {
    Person.total = 100; // 不用创建对象就可以访问静态成员
    //访问方式:类名.类属性,类名.类方法
    System.out.println(Person.total);
    Person c = new Person();
    System.out.println(c.total); //输出101
}}

静态变量的内存解析

类方法(class method)  

  • 没有对象的实例时,可以用类名.方法名()的形式访问由static修饰的类方法。
  • static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
class Person {
    private int id;
    private static int total = 0;
    public static int getTotalPerson() { 
        //id++; //非法
        return total;}
    public Person() {
        total++;
        id = total;
    }}
public class PersonTest {
    public static void main(String[] args) {
    System.out.println("Number of total is " + Person.getTotalPerson());
    //没有创建对象也可以访问静态方法
    Person p1 = new Person();
    System.out.println( "Number of total is "+ Person.getTotalPerson());
}}
因为不需要实例就可以访问 static 方法,因此 static 方法内部不能有 this ( 不能有 super ? YES!)  static 修饰的方法不能被重写
class Person {
    private int id;
    private static int total = 0;
    public static void setTotalPerson(int total){
        this.total=total; //非法,在static方法中不能有this,也不能有super
    }
public Person() {
    total++;
    id = total;
    }}
public class PersonTest {
    public static void main(String[] args) {
        Person.setTotalPerson(3);
} }

单例 (Singleton)设计模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 以及解决问题的思考方式。设计模免去我们自己再思考和摸索。就像是经典 的棋谱,不同的棋局,我们用不同的棋谱。套路

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对 某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 如果我们要让类在一个虚拟机中只能产生一个对象,

我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无 法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的

饿汉式

class Singleton {
    // 1.私有化构造器
    private Singleton() {
    }
    // 2.内部提供一个当前类的实例
    // 4.此实例也必须静态化
private static Singleton single = new Singleton();
    // 3.提供公共的静态的方法,返回当前类的对象
    public static Singleton getInstance() {
    return single;
    }
}
懒汉式
class Singleton {
// 1.私有化构造器
    private Singleton() {
    }
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single;
    // 3.提供公共的静态的方法,返回当前类的对象
    public static Singleton getInstance() {
        if(single == null) {
            single = new Singleton();
        }
    return single;
    }
}
由于单例模式只生成一个实例, 减少了系统性能开销 ,当一个对象的 产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可 以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
- 应用场景
  • 网站的计数器,一般也是单例模式实现,否则难以同步。
  • 应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志 文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  • 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库 资源。
  • 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
  • Application 也是单例的典型应用
  • WindowsTask Manager (任务管理器)就是很典型的单例模式
  • WindowsRecycle Bin (回收站)也是典型的单例应用。在整个系统运行过程 中,回收站一直维护着仅有的一个实例

理解main方法的语法

由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是 public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须 是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。

又因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情 况,我们在之前的例子中多次碰到

public class CommandPara {
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}
// 运行程序 CommandPara.java
java CommandPara “Tom" “Jerry" “Shkstart"

代码块

码块(或初始化块)的作用: Java类或对象进行初始化

代码块(或初始化块)的分类:

  • 一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块 (static block),
  • 没有使用static修饰的,为非静态代码块

static代码块通常用于初始化static的属性

class Person {
    public static int total;
    static {
        total = 100;//为total赋初值
    }
    …… //其它属性或方法声明
}
静态代码块:用 static 修饰的代码块
  • 1. 可以有输出语句。
  • 2. 可以对类的属性、类的声明进行初始化操作。
  • 3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
  • 4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  • 5. 静态代码块的执行要先于非静态代码块。
  • 6. 静态代码块随着类的加载而加载,且只执行一次。

非静态代码块:没有static修饰的代码块

  • 1. 可以有输出语句。
  • 2. 可以对类的属性、类的声明进行初始化操作。
  • 3. 除了调用非静态的结构外,还可以调用静态的变量或方法。
  • 4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  • 5. 每次创建对象的时候,都会执行一次。且先于构造器执行。

静态初始化块举例

class Person {
    public static int total;
    static {
        total = 100;
        System.out.println("in static block!");
    }
}
public class PersonTest {
    public static void main(String[] args) {
        System.out.println("total = " + Person.total);
        System.out.println("total = " + Person.total);
    }
}
//in static block
//total=100
//total=100
程序中成员变量赋值的执行顺序

  • 声明成员变量的默认初始化
  • 显式初始化、多个初始化块依次被执行
  • \构造器再对成员进行初始化操作(同级别下按先后顺序执行)
  • 通过”对象.属性”或”对象.方法”的方式,可多次给属性赋值

关键字:final

Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。

  • final标记的类不能被继承。提高安全性,提高程序的可读性。 String类、System类 StringBuffer
  • final标记的方法不能被子类重写。 比如:Object类中的getClass()
  • final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次
  • final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用。 final double MY_PI = 3.14;
 //final修饰类 中国古代,什么人不能有后代,就可以被final声明,称为“太监类”!
final class A{
}
class B extends A{ //错误,不能被继承。
}

//final修饰方法
class A {
    public final void print() {
        System.out.println("A");
    }
}
class B extends A {
    public void print() { // 错误,不能被重写。
        System.out.println("B");
    }
}

// final修饰变量——常量 常量名要大写,内容不可修改。——如同古代皇帝的圣旨。

class A {
    private final String INFO = "1"; //声明常量
     public void print() {
    //The final field A.INFO cannot be assigned
    //INFO = "ONE";
    }
}

//static final:全局常量
关键字 final 应用举例
public final class Test {
    public static int totalNumber = 5;
    public final int ID;
    public Test() {
        ID = ++totalNumber; // 可在构造器中给final修饰的“变量”赋值
    }
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.ID);
        final int I = 10;
        final int J;
        J = 20;
        J = 30; // 非法
    }
}

总结

package com.jyc.p2;
/*
* 一.static关键字的使用
*   static可以用来修饰 属性 方法 构造器 内部类
*   使用static修饰属性 :静态变量
*       属性使用static修饰又分为静态属性(类变量) vs 非静态属性(实例变量)
*       实例变量:我们创建了类的多个对象,每个对象都有独立的一套类中的非静态属性.当修改一个对象中的
*                非静属性时,不会导致对象中同样的属性值的修改
*       静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量
*                其他对象调用此静态变量时,是修改过的
*      static修饰符的其他说明
*         1.静态变量随着类的加载而加载(可以通过类.静态变量的方式进行调用)
*         2.静态变量的加载要早于对象的创建
*         3.由于类只会加载一次,则静态变量在内存中也会存在一份,存在方法区的静态域中
*         4.类不可以调用实例变量
*
*      例如 System.out  Math.PI
*
*   使用static修饰方法
*    1. 随着类的加载而加载,可以通过类.静态方法的方式进行调用
*    2.不能调用非静态方法
*    3.静态方法中只能调用静态的方法或属性,非静态的方法中,既可以调用非静态的方法和属性,也可以调用静态
*    的方法和属性
*
*   static注意点
*   在静态的方法内不能使用this super 关键字
*   从生命周期的角度理解
*   属性是可以被多个对象共享的,不会随着对象的不同而不同
*   操作静态的方法,通常设置为static
*   工具类中的方法,习惯上声明为static 比如 Math.Arrays
*
* 二 单例设计模式
*  所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,
*
* 饿汉式 vs 懒汉式
* 懒汉式 :延迟 对象的创建
* 饿汉式: 对象加载时间过长,线程安全
*
* 三 main方法的使用
*   1.mian()程序的入口
*     public static void main(String[] args) {}(也是普通的静态方法)
*     也可以作为我们与控制台交互的方式
*
* 四 代码块(或者初始化)
*   1.代码块的作用 用来初始化类 对象
*   2.代码块只能使用static修饰
*   3.分类 静态代码块 vs 非静态代码块
*   5.静态代码块
*       内部可以有输出语句
*       随着类者加载而执行,而且只执行一次
*       初始化类信息
*       如果一个类中定义了多个代码块,则按照声明的先后顺序执行
*       静态代码块的执行由于非静态代码块
*       静态代码块内可以调用静态属性静态方法,不能调用非静态结构
*
*     非静态代码块
*       内部可以有输出语句
*       随着对象的创建而执行,每创建一个对象执行一次
*       作用:可以对对象的属性进行初始化
*       如果一个类中定义了多个代码块,则按照声明的先后顺序执行
*       非静态代码块可以调用静态属性,静态方法 或非静态属性 非静态方法
*
*   属性可以赋值的位置
*   1.默认初始化
*   2.显示初始化
*   3.构造器中初始化
*   4.有了对象以后 可以对象.属性 对象.方法进行初始化
*   5.代码块中赋值
*   赋值顺序 1--> 2/5--> 3 -->4
*
* 五  final关键字 最终的
*  final 可以修饰的结构  类 方法 变量
*
*  final修饰一个类 此类不能够在继承
*   比如 String System
*
*  final修饰一个方法 表明方法不可以被重写
*    比如 object.getClass()
*
*  final可以用来修饰变量  此时的变量就是常量了
     final修饰属性 可以考虑赋值的位置有 显示初始化 代码块中 构造器中
     final修饰属性 修饰局部变量
        尤其是final修饰形参时,表明形参是一个常量,当我们调用此方法时给常量形参赋一个实参
        一但赋值以后,就只能在方法体内使用形参,但不能重新赋值
     static final:用来修饰属性 全局常量
     static final:用来修饰方法 不能被继承


* */
public class test1 {
    public static void main(String[] args) {
        Chinese c1=new Chinese("zs",18);
        Chinese c2=new Chinese("ls",22);
        c1.nation="中国";

        System.out.println(c2.nation);
        System.out.println("-----------单例设计模式饿汉式-------");
        Bank bank1=Bank.getInstance();
        Bank bank2=Bank.getInstance();
        System.out.println(bank1==bank2);
        System.out.println("-----------代码块-------");

        System.out.println(Chinese.desc);
        System.out.println(c2.language);

    }
}
class Chinese{
    String name;
    int age;
    String language;
    final  int width=10;
    final  int left;
    final  int right;
    static  String nation;
    static  String desc="我是一个人";
    Chinese(){
        right=100;
    }
    Chinese( String name, int age){
        this.age=age;
        this.name=name;
        right=100;

    }

    public  static  void show(){
        System.out.println("show执行");
        //name="tom";无法从静态上下文中引用非静态 变量
        nation="中国";//可以调用静态结构
    }
    //代码块
    {
        System.out.println("代码块");
        language="汉语";
        show();
        left=100;
    }
    static {
        System.out.println("静态代码块");
        desc="我是一个中国人";
        show();
    }
}
//饿汉式
 class Bank{
    //私有化类的构造器
     private  Bank(){}
     //内部创建类的对象(要求此对象必须为静态的)
     private  static  Bank instance=new Bank();

     //通过公共的静态对象 返回类的对象
     public  static  Bank getInstance(){
         return  instance;
     }
 }
 //饿汉式
 class Change{
    private  Change(){}
    //声明当前类对象,没有初始化
    private   static  Change instance =null;
    //声明public static的返回当前类对象方法
    public  static Change getInstance(){
        if (instance==null){
            instance= new Change();
      }
    return  instance;
}

 }

// class  C extends  String{} 不能继承

//class A{  不能重写
// final public  void  show(){}
//}
//class  B extends  A{
//    public  void  show(){}
//}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java面向对象 final && static 关键字 的相关文章

随机推荐

  • (python)常见面试题

    1 一行代码实现1 100之和 2 如何在一个函数内部修改全局变量 3 列出5个python标准库 os 提供了不少与操作系统相关联的函数 sys 通常用于命令行参数 re 正则匹配 math 数学运算 datetime 处理日期时间 4
  • Redis数据实战之“万金油”的String,为什么不好用了?

    Redis数据实战之 万金油 的String 为什么不好用了 引言 为什么 String 类型内存开销大 用什么数据结构可以节省内存 如何用集合类型保存单值的键值对 引言 以一个项目需要为例 需要开发一个图片存储系统 要求这个系统能快速地记
  • DNS使用TCP与UDP

    DNS同时占用UDP和TCP端口53是公认的 这种单个应用协议同时使用两种传输协议的情况在TCP IP栈也算是个另类 但很少有人知道DNS分别在什么情况下使用这两种协议 先简单介绍下TCP与UDP TCP是一种面向连接的协议 提供可靠的数据
  • tensorflow-ssd 实现纸张缺陷检测

    环境 win10 tensorflow1 10 python3 6 9 下载https github com balancap SSD Tensorflow到本地 1 解压并测试demo 打开Anaconda prompt 切换到SSD T
  • 我又把HTMLTestRunner改了一下,支持Python3,添加echarts统计饼图

    之前用Bootstrap把HTMLTestRunner改的美观了一点 同时改成了中文的报告 但那个是基于Python2的 见这篇博文 selenium之 输出报告 对HTMLTestRunner进行样式调整后的示例 这次呢 博主又给它改成了
  • mac编译安装Nginx

    一 安装wget 使用homebrew安装wget brew install wget 安装wget时报错 tar Error opening archive Failed to open Users xxx Library Caches
  • 【数据库】如何创建一个非常便宜的无服务器数据库

    云对象存储可以用作功能强大且非常便宜的数据库 您是否相信您可以使用完全托管 可大规模扩展 高度可用且价格低廉的无服务器数据库 每月只需 5 美元 您就可以存储数亿条记录并读写数十亿条记录 如果您的数据库需求可以通过非常简单的键值存储来满足
  • 近期deep learning做图像质量评价(image quality assessment)的论文4

    1 2017会议论文ICME An accurate deepconvolutional neural networks model for no reference image quality assessment 复旦大学 1 1用了部
  • Python开发环境Wing IDE如何查看调试数据

    Wing IDE具有一个十分有用的特性 就是处理复杂bug的时候可以以各种各样的方式查看调试数据值 这个功能具体是由Watch工具实现的 查看数据值 在PrintAsHTML中发生异常时 右键单击Stack Data工具中的本地数值 这将显
  • 【STM32学习笔记】(13)——外部中断详解

    EXTI 简介 EXTI External interrupt event controller 外部中断 事件控制器 管理了控制器的 20 个中断 事件线 每个输入线可以独立地配置输入类型 脉冲 或挂起 和对应的触发事件 上升沿或下降沿或
  • unity本地分数排行榜简单解决方案(Json)

    具体效果 大体方法 创建一个分数类Score和一个分数类的容器List
  • TLSv1.2抓包解密分析过程之ECDHE_RSA_WITH_AES_128_CBC_SHA256

    ECDHE RSA WITH AES 128 CBC SHA256模式下 RSA只用于身份验证 不用于加密 加密密钥是通过有限域的椭圆曲线算法交换的 需要拿到ECDH的私钥才能解密 本文的demo样本使用了特殊方法来获取这些参数 椭圆曲线加
  • Nginx 通过upstream反向代理报 400 Bad Request

    首先看一下400错误的定义 400 Bad Request 是一种 HTTP 错误状态码 HTTP 1 1 对 400 Bad Request的定义主要是 语义有误 当前请求无法被服务器理解 请求参数有误 丢包导致异常 背景一 开发了一个s
  • 从一道题目学习Nunjucks模板

    Nunjucks简介 Nunjucks 是一个功能丰富 强大的 JavaScript 专用模板引擎 Nunjucks 提供丰富的语言特性和块继承 自动转移 宏和异步控制等等 重点要关注的是 Nunjucks 模板引擎的代码在沙箱环境中运行
  • xilinx xdma PCIe中断bug

    xilinx xdma PCIe中断存在bug bug1 此中断虽然是msi或者msx中断 但是不中断cpu bug2 此中断不是边沿中断 而是电平中断 在驱动层需要不断地轮训查询中断事件 bug3 此中断持续时间必须长 而且在收到中断应答
  • 关于the selection cannot be run on any server错误的问题,如何快速的解决。

    最近在导入外来项目时 遇到了一个难题 就是出现了图中的错误 the selection cannot be run on any server 无法在任何服务器上运行所选内容 这个错误的原因在于Dynamic Web Module 的版本与
  • 基于CNN-GRU的多维数据预测算法——附带Matlab代码

    基于CNN GRU的多维数据预测算法 附带Matlab代码 近年来 卷积神经网络 CNN 和门控循环单元 GRU 在时序数据处理中的应用十分广泛 本文提出了一种基于CNN GRU结构的多维数据预测算法 并提供了相应的Matlab代码 首先
  • FPGA Xilinx 7系列高速收发器GTX通信

    Xilinx 7系列高速收发器GTX 说明 FPGA TX端 zynq 7z035 RX端 zynq 7z100 两个FPGA通过SFP 光纤 接口相连进行GTX的通信 环境 Vivado2018 2 IP核 7 Series FPGAs
  • radius认证服务器无响应,squid radius认证“RADIUS服务器没有响应”

    我已经用mysql成功配置freeradius 我可以radtest使用命令 squid radius认证 RADIUS服务器没有响应 sudo radtest alice password 192 168 2 3 1812 testing
  • java面向对象 final && static 关键字

    目录 关键字 static 类属性 类方法的设计思想 类变量 class Variable 静态变量的内存解析 类方法 class method 单例 Singleton 设计模式 理解main方法的语法 代码块 关键字 final 总结