-
2017-09-22 18:07:02
1.静态常量
public const int constValue= 1;
静态常量只能声明简单的数据类型,如:整型、浮点型、枚举或字符串。故静态常量属于值类型,不可以用new来初始化静态常量,用const定义的常量需要用访问静态常量的方式去访问,用访问对象成员的方式访问就会报错。
静态常量在编译时,编译器会自动将它替换成其对应的值,例如:
int num = constValue;
和
int num = 1;
编译后产生的结果相同,所以如果想改变静态常量的值就必须重新编译。
无内存的消耗。
综述:静态常量性能略高,无内存开销,但是限制多,使用不灵活。
2.动态常量
public static readonly readonlyValue = 1;
动态常量和类的其他成员一样,拥有独立的空间。
动态常量除了在定义的时候可以设定常量值外,还可以在构造函数中进行设置。
动态常量可以是任意的数据类型。
综述:动态常量使用灵活,方便,但性能更低,并且有内存开销。
两者对比:
静态常量 动态常量
定义 声明时必须为其设置值 声明时可以不设置,可以在析构函数中设置
类型限制 类型必须在值类型范围内,且不能 没有限制,可以用它定义任何类型的常量
用new来初始化。
内存消耗 无 要分配内存,用于保存常量实体
建议用动态常量来替换静态常量。
更多相关内容 -
C#静态常量和动态常量的区别
2018-05-23 14:39:01C#拥有两种不同的常量:静态常量(compile-time constants)和动态常量(runtime constants)。它们有不同的特性,错误的使用不仅会损失效率,还可能造成错误。相比之下,静态常量在速度上会稍稍快一些,但是灵活性却...C#拥有两种不同的常量:静态常量(compile-time constants)和动态常量(runtime constants)。它们有不同的特性,错误的使用不仅会损失效率,还可能造成错误。相比之下,静态常量在速度上会稍稍快一些,但是灵活性却比动态常量差很多。
//静态常量(隐式是静态的)
public const int compiletimeConstant = 1;
//动态常量
public static readonly runtimeConstant = 1;
静态常量在编译时会将其替换为所对应的值,也就是说下面这2句话通过编译器编译后产生的IL是一样的。
//通过编译后二者会被翻译成相同的中间语言
int myNum = compiletimeConstant;
int myNum = 1;
动态常量的值是在运行时获得的。IL中将其标为只读常量,而不是用常量的值代替。
静态常量只能被声明为简单的数据类型(内建的int和浮点型)、枚举或字符串。下面的程序段是通不过编译的。你不能用new关键字初始化一个静态常量,即便是对一个值类型来说。
//这样是错误的
public const DateTime myDateTime = new DateTime(2006,9,1,0,0,0);
//这样是可以的
public static readonly DateTime myDateTime = new DateTime(2006,9,1,0,0,0);
只读数据也是常量的一种,它们不能在构造器初始化之后被修改。但是它同静态常量不同,它的值是在运行时才被指派的,因此就会获得更大的灵活性。动态常量可以是任意的数据类型。
二者最大的差别在于:静态常量在编译时会将其换为对应的值,这就意味着对于不同的程序集来说,当你改变静态常量的时候需要将其重新编译,否则常量的值不会发生变化,可能引发潜在的问题,而动态常量就不会有这种情况。
用const定义的常量(隐式是静态的),需要像访问静态成员那样去访问const定义的常量,而用对象的成员方式去访问会出编译错误。 声明的同时要设置常量值。
从另一方面来说,如果你的确要声明一些从不改变且处处唯一的常量,例如钩子函数SetWindowsHookEx的idHook参数或序列化时的版本等,就应该使用静态常量。但是用到这样的常量的机会不多。一般来说我们应该使用灵活性更高的动态常量。
静态常量 动态常量
内存消耗 无 因为要保存常量 有消耗
初始化 很少的简单类型, 任意类型,可以在类构造函数中赋值
不能new,必须在
声明同时赋值
何时发挥作用 编译时进行替换 相当于类中的数据成员 -
c# 静态常量与动态常量
2022-05-10 14:12:131.静态常量(编译时常量)const 在编译时就确定了值,必须在声明时就进行初始化且之后不能进行更改,可在类和方法中定义。定义方法如下: const double a=3.14;// 正确声明常量的方法 const int b; // 错误,没有...1.静态常量(编译时常量)const
在编译时就确定了值,必须在声明时就进行初始化且之后不能进行更改,可在类和方法中定义。定义方法如下:
const double a=3.14;// 正确声明常量的方法 const int b; // 错误,没有初始化
2.动态常量(运行时常量)readonly
在运行时确定值,只能在声明时或构造函数中初始化,只能在类中定义。定义方法如下:class Program { readonly int a=1; // 声明时初始化 readonly int b; // 构造函数中初始化 Program() { b=2; } static void Main() { } }
在下面两种情况下:
a、取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)。 b、对程序性能要求非常苛刻。
可以使用 const 常量,除此之外的其他情况都应该优先采用 readonly 常量。
-
C# 静态常量与动态常量
2019-01-07 14:00:13什么是静态常量(Const)和动态常量(Readonly) 静态常量(Const)和动态常量(Readonly)之间的区别 动态常量(Readonly)被赋值后不可以改变 总结 什么是静态常量(Const)和动态常量(Readonly) 先解释下...目录
什么是静态常量(Const)和动态常量(Readonly)
先解释下什么是静态常量(Const)以及什么是动态常量(Readonly)。
静态常量(Const)是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。
动态常量(Readonly)的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。静态常量(Const)和动态常量(Readonly)之间的区别
静态常量(Compile-time Constant)
动态常量(Runtime Constant)
定义
声明的同时要设置常量值。
声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置。
类型限制
只能修饰基元类型,枚举类型或者字符串类型。
没有限制,可以用它定义任何类型的常量。
对于类对象而言
对于所有类的对象而言,常量的值是一样的。
对于类的不同对象而言,常量的值可以是不一样的。
内存消耗
无。
要分配内存,保存常量实体。
综述
性能要略高,无内存开销,但是限制颇多,不灵活。
灵活,方便,但是性能略低,且有内存开销。
- Const修饰的常量在声明的时候必须初始化;Readonly修饰的常量则可以延迟到构造函数初始化 。
- Const常量既可以声明在类中也可以在函数体内,但是Static Readonly常量只能声明在类中。Const是静态常量,所以它本身就是Static的,因此不能手动再为Const增加一个Static修饰符。
- Const修饰的常量在编译期间就被解析,即:经过编译器编译后,我们都在代码中引用Const变量的地方会用Const变量所对应的实际值来代替; Readonly修饰的常量则延迟到运行的时候。
举个例子来说明一下:
View Code
以上是语法方面的应用,那在实际的用法上,还是有些微妙的变化,通常不易发觉.
举个例子来说明一下:
在程序集DoTestConst.dll 中有一个类MyClass,定义了一个公开的静态变量Countpublic static class MyClass { public const int Count = 10; }
然后另外一个应用程序中引用DoTestConst.dll,并在代码中作如下调用:
public static void Main(string[] args) { Console.WriteLine(DoTestConst.MyClass.Count);//输出10 Console.ReadKey(); }
毫无疑问,非常简单的代码,直接输出10。
接下来更新MyClass的Count的值为20,然后重新编译DoTestConst.dll,并更新到应用程序的所在目录中,注意不要编译应用程序。那么这时候的输出结果按预期那么想应该是20才对,但实际上还是10,为什么呢?
这就是Const的特别之处,有多特别还是直接看生成的IL,查看IL代码(假设这时候Count的值为10)IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: call void [mscorlib]System.Console::WriteLine(int32)红色代码很明显的表明了,直接加载10,没有通过任何类型的加载然后得到对应变量的,也就是说在运行时没有去加载DoTestConst.dll,那么是否意味着没有DoTestConst.dll也可以运行呢?答案是肯定的,删除DoTestConst.dll也可以运行,是否很诡异呢?也就解释了之前的实验,为什么更新Const变量的值之后没有调用新的值,因为程序在运行的时候根本不会去加载DoTestConst.dll。那么10这个值是从哪来的呢?实际上CLR对于Const变量做了特殊处理,是将Const的值直接嵌入在生成的IL代码中,在执行的时候不会再去从dll加载。这也带来了一个不容易发觉的Bug,因此在引用其他程序集的Const变量时,需考虑到版本更新问题,要解决这个问题就是把调用的应用程序再编译一次就ok了。但实际程序部署更新时可能只更新个别文件,这时候就必须用Readonly关键字来解决这个问题。
接下来看Readonly的版本:
public static class MyClass { public static readonly int Count = 10; }
调用方代码不变,接着看生成的IL代码:
IL_0000: nop
IL_0001: ldsfld int32 [DoTestConst]DoTestConst.MyClass::Count
IL_0006: call void [mscorlib]System.Console::WriteLine(int32)很明显加载代码变了,一个很常见的ldsfld动作,请求了DoTestConst.MyClass的Count变量,是通过强制要求加载DoTestConst来实现的。因此这时候更新Count的值重新编译之后,还是不编译调用程序,然后再执行就会看到新的值。而这时候如果删除DoTestConst.dll那么,会出现找不到dll之类的异常。这也充分说明了对于Readonly定义的变量是在运行时加载的。
动态常量(Readonly)被赋值后不可以改变
ReadOnly 变量是运行时变量,它在运行时第一次赋值后将不可以改变。其中“不可以改变”分为两层意思:
- 对于值类型变量,值本身不可以改变(Readonly, 只读)
- 对于引用类型变量,引用本身(相当于指针)不可改变。
值类型变量,举个例子说明一下:
public class Student { public readonly int Age; public Student(int age) { this.Age = age; } }
Student的实例Age在构造函数中被赋值以后就不可以改变,下面的代码不会编译通过:
Student student = new Student(20); student.Age = 21; //错误信息:无法对只读的字段赋值(构造函数或变量初始化器中除外)
引用类型变量,举个例子说明一下:
public class Student { public int Age; //注意这里的Age是没有readonly修饰符的 public Student(int age) { this.Age = age; } } public class School { public readonly Student Student; public School(Student student) { this.Student = student; } }
School实例的Student是一个引用类型的变量,赋值后,变量不能再指向其他任何的Student实例,所以,下面的代码将不会编译通过:
School school = new School(new Student(10)); school.Student = new Student(20);//错误信息:无法对只读的字段赋值(构造函数或变量初始化器中除外)
引用本身不可以改变,但是引用说指向的实例的值是可以改变的。所以下面的代码是可以编译通过的:
School school = new School(new Student(10)); school.Student.Age = 20;
在构造方法中,我们可以多次对Readonly修饰的常量赋值。举个例子说明一下:
public class Student { public readonly int Age = 20;//注意:初始化器实际上是构造方法的一部分,它其实是一个语法糖 public Student(int age) { this.Age = age; this.Age = 25; this.Age = 30; } }
总结
Const和Readonly的最大区别(除语法外)
Const的变量是嵌入在IL代码中,编译时就加载好,不依赖外部dll(这也是为什么不能在构造方法中赋值)。Const在程序集更新时容易产生版本不一致的情况。
Readonly的变量是在运行时加载,需请求加载dll,每次都获取最新的值。Readonly赋值引用类型以后,引用本身不可以改变,但是引用所指向的实例的值是可以改变的。在构造方法中,我们可以多次对Readonly赋值。 -
静态常量和动态常量
2012-09-02 13:45:56静态常量:编译器在编译时进行解析,并对其进行初始化; 动态常量:运行时进行初始化。 区别与联系: 静态常量 动态常量 初始化 声明时初始化 可以在构造方法中初始化 类型限制 类型... -
静态变量和静态常量的区别
2021-03-09 01:05:23Java静态变量、静态常量、静态方法静态变量和静态方法都属于静态对象。在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法... -
方法区和常量池 及 静态常量池和动态常量池
2019-04-14 16:40:15小菜先拙劣的表达一下jvm虚拟内存分布: 程序计数器是jvm执行程序的流水线,存放一些跳转... 方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。 虚拟机堆是jvm执行jav... -
静态常量与动态常量的最直观区别
2020-03-30 09:18:11静态常量在程序编译时给值,且在整个程序编译周期内无法改变,无法做到用配置文件给值,较动态常量灵活性不足,但内存消耗非常低。 动态常量在程序运行时给值,且在赋值之后的整个程序运行周期内无法改变,可以做到... -
JAVA中使用双括号来初始化静态常量的小技巧
2020-09-04 10:23:11主要介绍了JAVA中使用双括号来初始化静态常量的小技巧,需要的朋友可以参考下 -
变量、常量、静态变量、静态常量
2022-02-07 15:05:16静态变量、成员变量、常量 -
静态定义常量
2016-11-06 21:59:30java 定义静态常量 -
c#中静态常量与动态常量的区别
2018-08-23 10:50:23C#中动态常量(readonly)与静态常量(const)的区别 C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量) Const和Readonly的异同: 相同点: const和readonly的值一旦初始化则都不再可以... -
常量和静态的区别和详解
2019-11-25 19:42:24常量函数不能修改除了静态成员变量以外的变量 常量函数不能调用除了静态成员函数以外的其他函数 可以调用静态成员函数 可以对静态成员变量进行操作 常量对象、常量指针、常量引用使用const关键字创建。 不希望某..... -
C#读取静态类常量属性和值的实例讲解
2020-12-20 20:10:141.背景 最近项目中有一个需求需要从用户输入的值找到该值随对应的名字,由于其它模块已经定义了一份名字到值的一组常量,所以想借用该定义。...其次,编写提取该静态类常量Name和值的方法,如下所示。 Type t = t -
java的静态常量
2021-08-20 16:38:23静态常量表达式:final static int 变量名 = "abc"; 静态的变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过... -
kotlin中的静态常量的设置
2019-09-03 21:37:13我们在编写Java的代码的时候经常会用到静态常量和静态变量,那么我们在kotlin中该如何定义我们的静态常量和静态变量呢? Java的写法 public class SystemConstat{ /** * 静态常量 */ public... -
C++ 静态 常量
2017-06-06 11:24:381)静态成员变量 C++静态成员变量是用static修饰的成员变量,不属于对象的一部分,而是类一部分,因此可以在没有实例化任何对象的时候使用静态成员变量。但是必须初始化它。 由于静态变量只能被初始化一次,所以... -
定义静态常量
2020-01-31 10:00:07开发中,我们想在类中定义一个静态常量,通常使用public static final修饰的变量来完成定义。此时变量名用全部大写,多个单词使用下划线连接。 定义格式: public static final 数据类型 变量名 = 值; 如下演示:... -
Kotlin的静态常量写法
2021-06-01 09:26:52Kotlin的静态常量写法有两种 1 放到class外 2 companion object //1 放到class外 private const val UNSPLASH_STARTING_PAGE_INDEX = 1 class MyObject{ ... } //2 companion object class MyObject{ ... ... -
Java 反射修改类的常量值、静态变量值、属性值
2021-03-14 10:47:09前言有的时候,我们需要修改一个变量的值,但变量也许存在于 Jar 包中或其他位置,导致我们不能从代码层面进行修改,于是我们就用到了下面的...}利用反射修改私有静态常量方法System.out.println(Bean.INT_VALUE);Fi... -
7.C++静态和常量
2022-02-28 12:56:117.1静态static 所有的静态成员的内存在程序刚运行,第一时间就会创建内存 两种用法: 1.标注类的属性,所有的类对象都共用同一个静态成员属性,而且无需创建对象,直接用类名::也能直接操作静态属性 2.标注类的函数... -
静态常量(static final)在class文件里是如何的呢?
2021-03-15 12:47:13背景:由于项目小,没有使用配置文件,全部静态常量都放在Config.java里面了public class Config {public static final String URL="http://www.xxxx.com/";public static final int PAGE_NUM=10;}看起来也不错啊,... -
Java使用静态声明常量
2021-03-14 15:12:56示例由于该static关键字用于访问没有实例化类的字段和方法,因此可以用来声明用于其他类的常量。这些变量将在类的每个实例中保持不变。按照惯例,static变量始终是ALL_CAPS并且使用下划线而不是驼峰式大小写。例如:... -
C++类内静态常量定义和声明及enum hack
2017-07-22 16:33:31此篇文章介绍类内静态常量定义和声明的用法,在编程时经常遇到需要定义一个常量,而且如果要确保其的有效性在某个范围内,则需要将其定义在一个class内。而其用法常会遇到一些问题,下面简要说明其中会遇到的一个... -
如何给静态常量赋值(final)
2019-03-06 19:43:12有些变量从一开始运行就不变,在c/c++/c#中用const修饰;...这样,其他的类,就可以把它当成静态常量访问。 例: public final class Constants { public static final String OS_ARCH=Syst... -
Kotlin实战指南二:变量、常量、静态常量
2019-02-20 18:52:20本文出自【赵彦军的博客】 ...Kotlin初体验二:变量、常量、静态常量变量常量静态常量 变量 Java中的变量 public class App { private String name; //定义一个变量 } Kotlin中的变量,用 var... -
Java静态常量池和运行时常量池
2020-07-03 11:12:46Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。 所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分... -
如何通过反射获取静态常量类中的各个值
2021-02-28 06:58:42} } 成功输出YES和NO的值。 如果不是取得static属性,那么get方法的参数就不能是null,否则会抛出异常。如果是static,那么可以传入任何对象包括null,因为get方法会将该参数忽略。 其中字段必须是public,若想获取... -
java基础-静态变量和静态常量以及静态方法的理解
2018-05-23 13:22:56静态变量是用static修饰符修饰的变量,静态常量是final static修饰的变量;声明和访问权限:静态变量:必须是成员变量,static不能修饰局部变量 -
类调用静态常量和对象调用静态常量有什么不同
2020-09-07 19:04:16测试demo: public class Test { ... //类调用静态常量 public static void test() { System.out.println(constant); } //对象调用静态常量 public void test1() { System.out.println(this.co