精华内容
下载资源
问答
  • 2022-05-10 14:12:13

    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 常量。

    更多相关内容
  • 动态常量赋值

    2021-02-27 15:11:55
    因为Ruby中的常量并不是要改变,所以Ruby不鼓励你在可能多次执行的代码部分中分配它们,例如内部方法 .在正常情况下,您应该在类本身内部定义常量:class MyClassMY_CONSTANT = "foo"endMyClass::MY_CONSTANT #=>...

    因为Ruby中的常量并不是要改变,所以Ruby不鼓励你在可能多次执行的代码部分中分配它们,例如内部方法 .

    在正常情况下,您应该在类本身内部定义常量:

    class MyClass

    MY_CONSTANT = "foo"

    end

    MyClass::MY_CONSTANT #=> "foo"

    如果由于某种原因你确实需要在方法中定义一个常量(也许是某种类型的元编程),你可以使用const_set:

    class MyClass

    def my_method

    self.class.const_set(:MY_CONSTANT, "foo")

    end

    end

    MyClass::MY_CONSTANT

    #=> NameError: uninitialized constant MyClass::MY_CONSTANT

    MyClass.new.my_method

    MyClass::MY_CONSTANT #=> "foo"

    尽管如此,const_set isn 't something you should really have to resort to under normal circumstances. If you'不确定您是否真的想以这种方式分配常量,您可能需要考虑以下其中一种选择:

    类变量

    类变量在很多方面表现得像常量 . 它们是类的属性,可以在定义它们的类的子类中访问它们 .

    不同之处在于类变量是可修改的,因此可以在没有问题的情况下分配给内部方法 .

    class MyClass

    def self.my_class_variable

    @@my_class_variable

    end

    def my_method

    @@my_class_variable = "foo"

    end

    end

    class SubClass < MyClass

    end

    MyClass.my_class_variable

    #=> NameError: uninitialized class variable @@my_class_variable in MyClass

    SubClass.my_class_variable

    #=> NameError: uninitialized class variable @@my_class_variable in MyClass

    MyClass.new.my_method

    MyClass.my_class_variable #=> "foo"

    SubClass.my_class_variable #=> "foo"

    类属性

    类属性是一种“类上的实例变量” . 它们的行为有点像类变量,除了它们的值不与子类共享 .

    class MyClass

    class << self

    attr_accessor :my_class_attribute

    end

    def my_method

    self.class.my_class_attribute = "blah"

    end

    end

    class SubClass < MyClass

    end

    MyClass.my_class_attribute #=> nil

    SubClass.my_class_attribute #=> nil

    MyClass.new.my_method

    MyClass.my_class_attribute #=> "blah"

    SubClass.my_class_attribute #=> nil

    SubClass.new.my_method

    SubClass.my_class_attribute #=> "blah"

    实例变量

    为了完整起见,我应该提一下:如果你需要分配一个只能在你的类被实例化后才能确定的值,那么你很可能实际上正在寻找一个普通的旧实例变量 .

    class MyClass

    attr_accessor :instance_variable

    def my_method

    @instance_variable = "blah"

    end

    end

    my_object = MyClass.new

    my_object.instance_variable #=> nil

    my_object.my_method

    my_object.instance_variable #=> "blah"

    MyClass.new.instance_variable #=> nil

    展开全文
  • 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)

    定义

    声明的同时要设置常量值。

    声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置。

    类型限制

    只能修饰基元类型,枚举类型或者字符串类型。

    没有限制,可以用它定义任何类型的常量。

    对于类对象而言

    对于所有类的对象而言,常量的值是一样的。

    对于类的不同对象而言,常量的值可以是不一样的。

    内存消耗

    无。

    要分配内存,保存常量实体。

    综述

    性能要略高,无内存开销,但是限制颇多,不灵活。

    灵活,方便,但是性能略低,且有内存开销。

    1. Const修饰的常量在声明的时候必须初始化;Readonly修饰的常量则可以延迟到构造函数初始化 。
    2. Const常量既可以声明在类中也可以在函数体内,但是Static Readonly常量只能声明在类中。Const是静态常量,所以它本身就是Static的,因此不能手动再为Const增加一个Static修饰符。
    3. Const修饰的常量在编译期间就被解析,即:经过编译器编译后,我们都在代码中引用Const变量的地方会用Const变量所对应的实际值来代替; Readonly修饰的常量则延迟到运行的时候。

      举个例子来说明一下:

    View Code

      以上是语法方面的应用,那在实际的用法上,还是有些微妙的变化,通常不易发觉.
      举个例子来说明一下:
      在程序集DoTestConst.dll 中有一个类MyClass,定义了一个公开的静态变量Count

        public 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 变量是运行时变量,它在运行时第一次赋值后将不可以改变。其中“不可以改变”分为两层意思:

    1. 对于值类型变量,值本身不可以改变(Readonly, 只读)
    2. 对于引用类型变量,引用本身(相当于指针)不可改变。

      值类型变量,举个例子说明一下:

        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赋值。

    展开全文
  • 小菜先拙劣的表达一下jvm虚拟内存分布: 程序计数器是jvm执行程序的流水线,存放一些跳转... 方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。 虚拟机堆是jvm执行jav...

     小菜先拙劣的表达一下jvm虚拟内存分布:

    jvm虚拟内存分布

     

         程序计数器是jvm执行程序的流水线,存放一些跳转指令,这个太高深,小菜不懂。

         本地方法栈是jvm调用操作系统方法所使用的栈。

         虚拟机栈是jvm执行java代码所使用的栈。

         方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。

         虚拟机堆是jvm执行java代码所使用的堆。

         Java中的常量池,实际上分为两种形态:静态常量池运行时常量池

         所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。

         而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

         接下来我们引用一些网络上流行的常量池例子,然后借以讲解。

     

     

     1 String s1 = "Hello";
     2 String s2 = "Hello";
     3 String s3 = "Hel" + "lo";
     4 String s4 = "Hel" + new String("lo");
     5 String s5 = new String("Hello");
     6 String s6 = s5.intern();
     7 String s7 = "H";
     8 String s8 = "ello";
     9 String s9 = s7 + s8;
    10           
    11 System.out.println(s1 == s2);  // true
    12 System.out.println(s1 == s3);  // true
    13 System.out.println(s1 == s4);  // false
    14 System.out.println(s1 == s9);  // false
    15 System.out.println(s4 == s5);  // false
    16 System.out.println(s1 == s6);  // true

     

     

         首先说明一点,在java 中,直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容,比较内容请用String.equals()。

         s1 == s2这个非常好理解,s1、s2在赋值时,均使用的字符串字面量,说白话点,就是直接把字符串写死,在编译期间,这种字面量会直接放入class文件的常量池中,从而实现复用,载入运行时常量池后,s1、s2指向的是同一个内存地址,所以相等。

         s1 == s3这个地方有个坑,s3虽然是动态拼接出来的字符串,但是所有参与拼接的部分都是已知的字面量,在编译期间,这种拼接会被优化,编译器直接帮你拼好,因此String s3 = "Hel" + "lo";在class文件中被优化成String s3 = "Hello";,所以s1 == s3成立。

         s1 == s4当然不相等,s4虽然也是拼接出来的,但new String("lo")这部分不是已知字面量,是一个不可预料的部分,编译器不会优化,必须等到运行时才可以确定结果,结合字符串不变定理,鬼知道s4被分配到哪去了,所以地址肯定不同。配上一张简图理清思路:

    java字符串不变     s1 == s9也不相等,道理差不多,虽然s7、s8在赋值的时候使用的字符串字面量,但是拼接成s9的时候,s7、s8作为两个变量,都是不可预料的,编译器毕竟是编译器,不可能当解释器用,所以不做优化,等到运行时,s7、s8拼接成的新字符串,在堆中地址不确定,不可能与方法区常量池中的s1地址相同。
    jvm常量池,堆,栈内存分布

         s4 == s5已经不用解释了,绝对不相等,二者都在堆中,但地址不同。

         s1 == s6这两个相等完全归功于intern方法,s5在堆中,内容为Hello ,intern方法会尝试将Hello字符串添加到常量池中,并返回其在常量池中的地址,因为常量池中已经有了Hello字符串,所以intern方法直接返回地址;而s1在编译期就已经指向常量池了,因此s1和s6指向同一地址,相等。

         至此,我们可以得出三个非常重要的结论:

     

               必须要关注编译期的行为,才能更好的理解常量池。

               运行时常量池中的常量,基本来源于各个class文件中的常量池。

               程序运行时,除非手动向常量池中添加常量(比如调用intern方法),否则jvm不会自动添加常量到常量池。

     

         以上所讲仅涉及字符串常量池,实际上还有整型常量池、浮点型常量池等等,但都大同小异,只不过数值类型的常量池不可以手动添加常量,程序启动时常量池中的常量就已经确定了,比如整型常量池中的常量范围:-128~127,只有这个范围的数字可以用到常量池。

     

     

    静态常量池和动态常量池的关系以及区别

    静态常量池存储的是当class文件被java虚拟机加载进来后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量,符号引用其实引用的就是常量池里面的字符串,但符号引用不是直接存储字符串,而是存储字符串在常量池里的索引。

    动态常量池是当class文件被加载完成后,java虚拟机会将静态常量池里的内容转移到动态常量池里,在静态常量池的符号引用有一部分是会被转变为直接引用的,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法是在这个方法被第一次调用的时候才会将符号引用转变为直接引用的。

    总结:

    方法区里存储着class文件的信息和动态常量池,class文件的信息包括类信息和静态常量池。可以将类的信息是对class文件内容的一个框架,里面具体的内容通过常量池来存储。

    动态常量池里的内容除了是静态常量池里的内容外,还将静态常量池里的符号引用转变为直接引用,而且动态常量池里的内容是能动态添加的。例如调用String的intern方法就能将string的值添加到String常量池中,这里String常量池是包含在动态常量池里的,但在jdk1.8后,将String常量池放到了堆中。

     

     

         

    展开全文
  • 静态常量在程序编译时给值,且在整个程序编译周期内无法改变,无法做到用配置文件给值,较动态常量灵活性不足,但内存消耗非常低。 动态常量在程序运行时给值,且在赋值之后的整个程序运行周期内无法改变,可以做到...
  • C#中动态常量(readonly)与静态常量(const)的区别   C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量) Const和Readonly的异同: 相同点:  const和readonly的值一旦初始化则都不再可以...
  • C#拥有两种不同的常量:静态常量(compile-time constants)和动态常量(runtime constants)。它们有不同的特性,错误的使用不仅会损失效率,还可能造成错误。相比之下,静态常量在速度上会稍稍快一些,但是灵活性却...
  • 很明显,系统里面一开始肯定是没有"abcsfsdfsdfsdfsdfsdfsdgsgfdsgdsfsdghgfjghjfdgsdfs"这个常量的,但是随着系统的运行,这个常量出现,先去动态常量池检查是否已经存在,如果存在,则使用已有的,如果不存在,则...
  • C#中动态常量(readonly)与静态常量(const)的区别   C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量) Const和Readonly的异同: 相同点:  const和readonly的值一旦初始化则都不再可以...
  • C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景。 工作原理 readonly为运行时常量,程序运行时进行赋值,赋值完成后便无法更改,...
  • 静态常量和动态常量

    千次阅读 2012-09-02 13:45:56
    动态常量:运行时进行初始化。 区别与联系:   静态常量 动态常量 初始化 声明时初始化 可以在构造方法中初始化 类型限制 类型必须是值类型,且不能通过new来进行初始化 没有限制 ...
  • 1.静态常量 public const int constValue= 1; 静态常量只能声明简单的数据类型,如:整型、浮点型、枚举或字符串。故静态常量属于值类型,不可以用new来初始化静态常量,用const定义的常量需要用访问静态常量的方式...
  • 最近在学习c#,我在一个类中想调用另一个类的静态常量,可是调用不了,只可以调用动态常量?请问下这是为什么
  • 在C#中定义常量的方式有两种,一种叫做静态常量(Compile-time constant),另一种叫做动态常量(Runtime constant)。前者用“const”来定义,后者用“readonly”来定义。 对于静态常量(Compile-time constant),...
  • C#中含有两种常量:静态常量和动态常量,合适的利用可以提高程序的效率,错误的利用则会增加额外开销,甚至引发错误。  静态常量:const(隐式是静态的)  如 public const int compileData = 1;  动态常量:static...
  • 1、什么是常量用final修饰的成员变量表示常量,值一旦给定就无法改变!final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。Java中的常量池,实际上分为两种形态:静态常量池和运行时...
  • ·每一个栈帧内部都包含一个指向运行时...例如:描述一个方法调用了其他方法时,就是通过常量池中指向方法的符号引用来表示的,所以说动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用。 在此我们创建
  • 方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。 他也有一个别名为"非堆",目的是与Java堆区分开来。 方法区和永久代 ...
  • java常量定义规范

    2022-02-12 12:29:04
    1. 不允许出现任何魔法值( 即未经定义的常量) 直接出现在代码中。 反例: String key="Id#taobao_"+tradeId; cache.put(key, value); 2. long 或者 Long 初始赋值时,必须使用大写的 L,不能是小写的 l,小写...
  • ## 变量、常量的使用 1. 种类 变量: 静态变量、实例变量、局部变量 常量常量、静态常量 2.变量的使用 静态变量:被static 修饰,定义在所有方法体之外。 实例变量: 不被static修饰,定义在所有方法体之外。 ...
  • * 自PHP5.3.0起,可以用一个变量来动态调用类。但该变量的值不能为关键字(如self,parent或static)。 */ class Foo { // 常量值只能是标量,string,bool,integer,float,null,可以用nowdo
  • 2.常量是静态的,而只读字段可以是静态和动态的 3.Const可以用在字段和局部变量,readonly只可以修饰字段 您可能感兴趣的文章:C#学习笔记整理_变量等基础语法(必看篇)C#把整个文件内容读入字符串变量的方法C#中...
  • php动态获取常量

    2018-12-17 15:29:00
    class A1{ const V1='100'; const V2='200'; const V3='Hello world'; } $v1 = 'V3'; $a1 = constant('A1::'.$v1);...这个a1就等价于a2,做到动态获取常量的内容 转载于:https://ww...
  • springboot yml 常量

    千次阅读 2018-12-24 15:10:05
    springboot yml 常量 配置 1.当springboot yml 中配置: my: pro: on   在程序中获取my.pro的值,变成了true.  2.当springboot yml 中配置: my: pro: 'on' 在程序中获取my.pro的值,是on.  2.当...
  • springboot 根据不同配置文件来设定常量的值 原因:不同环境下(开发环境和正式环境)动态设置常量的值,比如将文件以绝对路径保存时,开发环境(windows系统)和正式环境(linux系统)的路径肯定是不同的,这时就...
  • 动态链接与常量

    2020-10-15 21:35:35
    1.每一个栈帧内部都包含一个指向运行常量池该栈帧所属方法的引用,包含这个引用的目的就是为了支持当前的方法代码能够实现动态链接。/ 2.在Java源文件被编译到字节码中时,所有的变量和方法引用都作为符号引用保存在...
  • 常量声明部分添加到vue组件。 这使您可以更好地陈述自己的意图,还可以避免vue在不变的值上创建观察者的开销。 通过安装 npm install vue-constants 通过在您的项目中启用它 import VueConstants from 'vue-...
  • c# 常量和字段

    2020-12-31 17:19:38
    编译器将常量保存到程序集的元数据中,所有只能是编译器认识的基元类型作为常量常量被看成类的一部分,是看出静态成员。 代码引用一个常量符号,会在定义常量的元数据中查找该符号,提取之,并嵌入代码,生成的IL...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 303,516
精华内容 121,406
关键字:

动态常量