精华内容
下载资源
问答
  • PHP类 const常量访问方法例子

    千次阅读 2015-11-11 10:31:59
    在php面向对象之final的应用中,讲到了PHP面向对象常用的修饰符final的应用,接下来讲到PHP面向对象中常用的常量修饰符const。 我们知道,在PHP中定义常量是通过define()函数来完成的,但在类中定义常量不能使用...

    php面向对象之final的应用中,讲到了PHP面向对象常用的修饰符final的应用,接下来讲到PHP面向对象中常用的常量修饰符const

    我们知道,在PHP中定义常量是通过define()函数来完成的,但在类中定义常量不能使用define(),而需要使用const修饰符。类中的常量使用const定义后,其访问方式和静态成员类似,都是通过类名或在成员方法中使用self访问,但在PHP 5.3.0之后也可以使用对象来访问。被const定义的常量不能重新赋值,如果在程序中试图改变它的值将会出现错误。

    <?php
         class MyClass {
              const CONSTANT = 'CONSTANT value' ; //使用const声明一个常量,并直接赋上初使值
                 function showConstant() {               
                      echo  self ::CONSTANT ."<br>" ;//使用self访问常量,注意常量前不要加“$”
                 }
         }
         echo MyClass:: CONSTANT . "<br>" ; //在类外部使用类名称访问常量,也不要加”$”
         $class = new MyClass();                     
         $class->showConstant();                      
         echo $class ::CONSTANT;  // PHP 5.3.0之后
    ?>

    关注细节:使用const定义的常量名称前不需要使用“$“符号,且常量名称通常都是大写的。


    试图为const定义的常量赋值,将会出现错误。

    <?php
         class MyClass {
              const CONSTANT = 'CONSTANT value' ;  
                  function setCONSTANT(){
                   self ::CONSTANT  = 'news CONSTANT' ;//程序运行结果将会出错。
          }
                                                                                                                                                                                          
         }
         echo MyClass:: CONSTANT ;          
                                                                                                                                                                                  
    ?>


    程序运行结果将会出错。


    展开全文
  • java类加载和常量的小例子

    千次阅读 2015-11-07 21:58:02
    通过下面的两个例子简单了解一下常量与类的加载的关系。 class FinalTest { static { System.out.println("static block "); } public static final int a = 6/3; } public class Test1 { public static ...

    通过下面的两个例子简单了解一下常量与类的加载的关系。

    class FinalTest
    {
    	static
    	{
    		System.out.println("static block ");
    	}
    	public static final int a = 6/3;
    	
    }
    
    public class Test1
    {
    	public static void main(String[] args)
    	{
    		System.out.println(FinalTest.a);
    	}
    	
    }
    输出结果为:2

    class FinalTest
    {
    	
    	public static final int a = 6/3;
    	static
    	{
    		System.out.println("static block ");
    	}
    }
    
    public class Test1
    {
    	public static void main(String[] args)
    	{
    		System.out.println(FinalTest.a);
    	}
    	
    }
    结果为:2

    import java.util.Random;
    
    class FinalTest2
    {
    	public static final int a = new Random().nextInt(10);
    	
    	static
    	{
    		System.out.println("static block 2");
    	}
    }
    
    public class Test2
    {
    	public static void main(String[] args)
    	{
    		System.out.println(FinalTest2.a);
    	}
    }
    结果为:6(随机的)

         static block 2

    import java.util.Random;
    
    class FinalTest2
    {
    	static
    	{
    		System.out.println("static block 2");
    	}
    	
    	public static final int a = new Random().nextInt(10);
    	
    	
    }
    
    public class Test2
    {
    	public static void main(String[] args)
    	{
    		System.out.println(FinalTest2.a);
    	}
    }

    结果为:4(随机的)

         static block 2

    四个程序不同的地方是a是否为常量还是变量,如果为常量时,在编译的时候就确定了值,所以不用加载就能够使用,而随机产生的在编译时不能确定a的值,只有在加载时才能够确定。

    结论:当一个类调用静态常量时,类是不会被加载。







    展开全文
  • 易语言-易语言写内存更改常量例子
  • 调皮的常量,通过取到常量的指针,将我们要改变的数据写进去
  • String类和常量池内存分析例子以及8种基本类型

    万次阅读 多人点赞 2019-01-21 19:52:51
    该篇例子几乎涵盖了目前所有能解决的类型,以一种通俗的语言讲解出来。当然如果JVM内存基本问题不太会可以看这里:JVM内存的基本问题 基本问题 String类和常量池内存分析 8种基本类型的包装类和常量池 String ...

    该篇例子几乎涵盖了目前所有能解决的类型,以一种通俗的语言讲解出来。当然如果JVM内存基本问题不太会可以看这里:JVM内存的基本问题

    目录

    String类和常量池内存分析

    说说String.intern()

    8种基本类型的包装类和常量池


     

    String类和常量池内存分析

    1 String 对象的两种创建方式

    String str1 = "abcd";

    String str2 = new String("abcd");

    System.out.println(str1==str2); // false

    记住:只要使用 new 方法,便需要创建新的对象。

    2 String 类型的常量池比较特殊。它的主要使用方法有两种:

    • 直接使用双引号声明出来的 String 对象会直接使用或创建常量池中对应的字符串。
    • 如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。

    说说String.intern()

    String.intern() 是一个 Native 方法,它的作用(在JDK1.6和1.7操作不同)是:

    如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则直接返回常量池中该字符串的引用;

    如果没有, 那么

    在jdk1.6中,将此String对象添加到常量池中,然后返回这个String对象的引用(此时引用的串在常量池)。

    在jdk1.7中,放入一个引用,指向堆中的String对象的地址,返回这个引用地址(此时引用的串在堆)。根据《java虚拟机规范 Java SE 8版》记录,如果某String实例所包含的Unicode码点序列与CONSTANT——String_info结构所给出的序列相同,而之前又曾在该实例上面调用过String.intern方法,那么此次字符串常量获取的结果将是一个指向相同String实例的引用。这是什么意思呢?如果看不懂这个例子没关系,跟着后面从问题一到问题八看一遍你就一定能明白的!!

            String a1 = new String("a"); // 创建"a",并把"a"缓存到常量池,占用2块内存空间
            String a2 = new String("b"); // 创建"b",并把"b"缓存到常量池,占用2块内存空间
            String a3 = new String("c"); // 创建"c",并把"c"缓存到常量池,占用2块内存空间
            System.out.println((a1+a2+a3).intern() == "abc");  // true,在堆中连接生成了"abc",调用intern()后发现常量池没有"abc",那么就把指向堆中的"abc"的引用放入常量池,返回值为这个引用。当执行这个表达式的时候,从左到右执行,左边是常量池指向堆中的引用,右边也是直接使用常量池的"abc"(其实就是指向堆中"abc"的引用),直接返回这个引用,两边引用都是堆里面连接生成的"abc"的地址,所以打印出true。

    Unicode码点序列的直接理解:这玩意不就是字符连起来看equals是否相同不就完了吗!咋这么墨迹~

    关于String的intern()问题,可参考这篇文章Java技术——你真的了解String类的intern()方法吗

    关于运行时常量池:java虚拟机为每个类型都维护着一个常量池。该常量池是java虚拟机中的运行时数据结构,像传统编程语言实现中的符号表一样有很多用途。当类或接口创建时,它的二进制表示中的常量池表被用来构造运行时常量池,运行时常量池中的所有引用最初都是符号引用。

    以下所说常量池为字符串常量池。

    接下来我们均以示例的方式来解释问题,也是我在某篇文章底下解决的别人问题的笔记。

    可能最颠覆你认知的是问题八,所以既然来看了,还是建议看到最后吧!

    问题一:

            String h = new String("cc");
            String intern = h.intern();
            System.out.println(intern == h); // 返回false

    这里为什么不返回true,而是返回false呢?

    解释:

    new String("cc")后,堆中创建了"cc","cc"也会缓存到常量池,可以认为占用了2个字符串对象内存(因为你创建了一个“cc”字符串对象,但是放到了2个地方占用了2块内存)!当你String intern = h.intern();其中h.intern()会去常量池检查是否有了"cc",结果发现有了,那么此时返回常量池的引用地址给intern,用常量池的引用intern和堆中的h引用去比较肯定不相等。所以返回false。

    在JDK中String也是类似于消息池,就是典型的享元模式,一个String被定义后就被缓存到常量池,当其他地方要使用同样的字符串时,就直接使用缓存而不是重复创建。

    问题二:

    我对以下代码的操作过程有疑问

    String str2 = new String("str") + new String("01");
    String str1 = "str01";
    str2.intern();
    System.out.println(str2 == str1); // false

    解释:

           第一句new String("str") + new String("01");现在在堆中创建了"str",同时"str"缓存到常量池,创建了"01",同时"01"也缓存到常量池,再进行连接,堆中出现了"str01"。此时常量池中有:"str","01",此时堆中有"str","01","str01"。str2引用指向堆中的"str01"。
           接着第二句String str1 = "str01"; 发现常量池没有"str01",那么直接在常量池创建"str01"。此时常量池中有:"str","01","str01",此时堆中有"str","01","str01"。str1指向常量池中的"str01"。
           接着第三句str2.intern();检查常量池是否有"str01",结果发现有了,返回常量池"str01"的地址,很可惜,没有变量去接收,所以这一句没什么用,str2指向也不会改变,还是指向堆中"str01"。 
           第四句去打印str2==str1,一个堆中的"str01"地址和一个常量池中的"str01"地址比较,返回false。

    问题三:

    那这一段代码呢?

            String str2 = new String("str") + new String("01");
            String str1 = "str01";
            String str3 = str2.intern();
            System.out.println(str3 == str1); // true

    解释:

    比问题二多了一个str3引用保存了常量池"str01",str3和str1均指向常量池的"str01",所以返回true

    问题四:

            String str2 = new String("str") + new String("01");
            str2.intern();
            String str1 = "str01";
            System.out.println(str2 == str1);
    
            String str3 = new String("str01");
            str3.intern();
            String str4 = "str01";
            System.out.println(str3 == str4);

    这个代码的过程晕乎了,到底这些串在堆还是在常量池呢?

    解释:

           第一句new String("str") + new String("01");现在在堆中创建了"str",同时"str"缓存到常量池,创建了"01",同时"01"缓存到常量池,再进行连接,堆中出现了"str01"。此时常量池中有:"str","01",此时堆中有"str","01","str01"。str2引用指向堆中的"str01"。 
           第二句,str2.intern();检查到常量池不存在"str01",如果在jdk1.6,那么就将堆中的"str01"添加到常量池中,如果是jdk1.7,那么就在常量池保存指向堆中"str01"的地址,即保存堆中"str01"的引用。接下来的讲解以jdk1.7为准!!所以这里是在常量池保存了堆中"str01"的引用。

           第三句,String str1 = "str01";检查到常量池有一个引用保存了这个串,str1就直接指向这个地址,即还是堆中的"str01"。

           第四句,str2==str1是否相等,str2指向堆中的"str01",str1指向常量池的某个地址,这个地址恰好是指向堆中的"str01",所以仍然是true。

           第五句,String str3 = new String("str01");又在堆中创建了"str01",现在堆中有了2个"str01",而常量池已经有"str01"引用,不再缓存进去。(结论是常量池有equals相同的串或者引用指向equals相同的串就不再缓存)

           第六句,str3.intern(); 去检查一下常量池到底有没有"str01"呢?检查发现常量池有个引用指向堆中的"str01",JVM认为常量池是有"str01"的,那么直接返回指向堆中的"str01"地址,很可惜,没有变量去接收,这一句在这里没有什么用。

           第七句,String str4 = "str01";检查到常量池有个引用指向堆中的"str01",那么str4也保存这个引用,所以这个"str01"还是堆中的第一个"str01"。

           第八句,打印str3==str4,str3是堆中新建的第二个"str01",str4保存引用指向第一个堆中的"str01",两块堆的地址,所以返回false。

    问题五:

     String str2 = new String("str") + new String("01");

    为什么不String str2 = new String("str01");呢? 区别在哪里呢?

    解释:

           我们来单独执行比较,前者new String("str")堆中创建"str",同时"str"缓存到常量池,new String("01")在堆中创建"01",同时"01"缓存到常量池,相加操作只会在堆中创建"str01",所以前者执行以后,内存:堆中有"str","01","str01",常量池中"str","01"。str2引用指向堆中的"str01"。
           现在来看后者String str2 = new String("str01");这个就是在堆中创建"str01"同时"str01"缓存到常量池,str2引用指向堆中的"str01",内存:堆中有"str01",常量池中有"str01"。
           综上所述,区别就在于这些串处于不同的位置,前者在常量池是没有"str01"的。

    问题六:

            String s = new String("abc"); 
            String s1 = "abc"; 
            String s2 = new String("abc"); 
            System.out.println(s == s1);// 堆内存"abc"和常量池"abc"相比,false
            System.out.println(s == s2);// 堆内存s和堆内存s2相比,false
            System.out.println(s == s1.intern());// 堆内存"abc"和常量池"abc"相比,false
            System.out.println(s == s2.intern());// 堆内存"abc"和常量池"abc"相比,false
            System.out.println(s1 == s2.intern());// 常量池"abc"和常量池"abc"相比,true
            System.out.println(s.intern() == s2.intern());// 常量池"abc"和常量池"abc"相比,true

    解释:有注释,无需多余解释,上面的问题看懂了这个一看就懂。

    问题七:

            String s1 = "abc"; 
            String s2 = "a"; 
            String s3 = "bc"; 
            String s4 = s2 + s3; 
            System.out.println(s1 == s4);//false,因为s2+s3实际上是使用StringBuilder.append来完成,会生成不同的对象。
            // s1指向常量池"abc",s4指向堆中"abc"(append连接而来)
            String S1 = "abc"; 
            final String S2 = "a"; 
            final String S3 = "bc"; 
            String S4 = S2 + S3; 
            System.out.println(S1 == S4);//true,因为final变量在编译后会直接替换成对应的值
            // 所以实际上等于s4="a"+"bc",而这种情况下,编译器会直接合并为s4="abc",所以最终s1==s4为true。

    问题八:

            String str1 = "abcd"; // 常量池创建"abcd"
            String str2 = "abcd"; // str2还是上一步的"abcd"
            String str3 = "ab" + "cd"; // 常量池创建"ab"和"cd",连接过程编译器直接优化成"abcd",而常量池已经有了"abcd",所以str3和str1都指向"abcd"
            String str4 = "ab"; // 常量池已经有了"ab"
            str4 += "cd"; // str4+"cd"连接的字符串编译器不能优化,所以此时str4指向堆中的"abcd"
            // 因为"ab"是str4引用的,如果是两个变量s1="ab", s2="cd",s1+s2连接,那么只有用final修饰的指向"ab"的s1和final修饰的指向"cd"的s2相连接才能优化成"abcd"
            // 如果只有一个变量s1和常量池的常量连接s1+"cd",这个变量s1也需要final修饰才会优化成"abcd"
            System.out.println(str1 == str2); // true
            System.out.println(str1 == str3); // true
            System.out.println(str1 == str4); // false
            System.out.println("================");
            String s1 = "a";
            String s2 = "b";
            String s3 = "ab";
            final String ss1 = "a";
            final String ss2 = "b";
            System.out.println(s1 + s2 == s3); // false, 有变量引用的字符串是不能优化的,除非变量是final修饰或者直接"a"+"b"的常量形式,这一行就是s1+s2生成堆里的"ab"和常量池的"ab"在比较
            System.out.println(ss1 + ss2 == s3); // true,原因见上一行,原理和下一行相同,都是常量连接
            System.out.println("a" + "b" == s3); // true,常量池的"a"和"b"连接,根据Copy On Write机制, 副本连接生成"ab",发现已存在,直接指向"ab",所以和s3相等
            

    验证一下确实生成了副本才进行连接: 

            String s = "ab";    // 常量池创建"ab"
            String s1 = new String("ab"); // 堆里面创建"ab",因为常量池已有"ab",不会在常量池再缓存一次
            String str3 = "ab" + "cd"; // 连接之后常量池是否还有"ab"??在常量池连接成"abcd"后"ab"和"cd"是否还存在?
            String s2 = s1.intern(); // 如果常量池还有"ab",s2指向常量池"ab",如果没有,则放入s1地址,s2就指向s1,即s2指向堆里的"ab"
            System.out.println(s2 == s1); // 如果true,则s2是堆里的"ab".说明"ab"+"cd"连接后,常量池只有"abcd","ab"和"cd"被回收了
            // 结果运行出来是false,说明"ab"+"cd"连接之后,不仅存在"ab","cd", 还存在"abcd"

           关于Java的String类这种在修改享元对象时,先将原有对象复制一份,然后在新对象上再实施修改操作的机制称为“Copy On Write”,大家可以自行查询相关资料来进一步了解和学习“Copy On Write”机制,在此不作详细说明。

    上面"ab"+"cd"就是"ab"生成"副本ab", "cd"生成"副本cd","副本ab" + "副本cd"被编译器优化成了"abcd",此时优化的副本不再存在,常量池就是"ab", "cd", "abcd"

     

    ("a"+"b"+"c").intern() == "abc"; //true

    "a"+"b"+"c" == "abc"; //true

    看看大家有没有理解?不妨再回到文章开头的例子看看自己能不能分析出来了。

     

    8种基本类型的包装类和常量池

    • Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte、Short、Integer、Long、Character、Boolean;这6种包装类会有相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。Byte、Short、Integer、Long缓存[-128, 127]区间的数据,Character缓存[0, 127]区间的数据,Boolean缓存true和false这两个Boolean对象。
    • 两种浮点数类型的包装类 Float、Double 并没有实现常量池技术。

    首先大家要知道自动装箱直接赋值就可以,比如 Integer a = 20;

    手动装箱有2种方式,一个是调用构造方法Integer a = new Integer(20);另一个是valueOf方法,Integer a = Integer.valueOf(20);

    为什么给大家强调手动装箱?知道调用valueOf,不就可以去看源码在做什么了吗?

    Integer i1 = 33;
    Integer i2 = 33;
    System.out.println(i1 == i2);// 输出true 
    Integer i11 = 333;
    Integer i22 = 333; 
    System.out.println(i11 == i22);// 输出false 
    Double i3 = 1.2; 
    Double i4 = 1.2; 
    System.out.println(i3 == i4);// 输出false
    Double i5 = Double.valueOf(100);
    Double i6 = Double.valueOf(100);
    System.out.println(i5 == i6);// 输出false

    在[-128,127]区间内的利用cache数组的值,否则new一个新的Integer对象。这里2个333不等因为是2块不同的堆内存。2个33相等是因为利用了同一个cache数组,是值的比较,这里i1==33,打印出来也是true。

    Integer 缓存源代码:

        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high) // Integer里面的high值可以配置,默认127,具体见源码
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }

    看源码可以知道除了Float、Double,其他基本类型的包装类都有对应的对象常量池缓存(就是cache数组缓存-128~127),Float、Double不管自动还是手动装箱,一定不相等,里面都是调用构造new出来的,比较2块堆内存,请自行查看valueOf源码验证。

        public static Double valueOf(double d) {
            return new Double(d);
        }

    应用场景:

    1. Integer i1=40;Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40); 从而使用常量池中的对象。
    2. Integer i1 = new Integer(40) ;这种情况下会创建新的对象。

    Integer i1 = 40; 
    Integer i2 = new Integer(40); 
    System.out.println(i1==i2); //输出false

    Integer 比较(==)更丰富的一个例子:

    Integer i1 = 40;
    Integer i2 = 40;
    Integer i3 = 0;
    Integer i4 = new Integer(40);
    Integer i5 = new Integer(40);
    Integer i6 = new Integer(0);
    System.out.println("i1=i2   " + (i1 == i2));
    System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
    System.out.println("i1=i4   " + (i1 == i4));
    System.out.println("i4=i5   " + (i4 == i5));
    System.out.println("i4=i5+i6   " + (i4 == i5 + i6));
    System.out.println("40=i5+i6   " + (40 == i5 + i6));

    结果:

    i1=i2   true

    i1=i2+i3   true

    i1=i4   false

    i4=i5   false

    i4=i5+i6   true

    40=i5+i6   true

    解释:

    语句 i4 == i5 + i6,因为 + 这个操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加,即 i4 == 40。然后Integer对象无法与数值进行直接比较,所以i4自动拆箱转为int值40,最终这条语句转为40 == 40进行数值比较。

     

    关注、留言,我们一起学习。 
     

    ===============Talk is cheap, show me the code================

    展开全文
  • java代码-例子2-1定义并输出常量和变量
  • java代码-例子2-1 定义并输出常量和变量
  • String常量池问题的几个例子

    千次阅读 2016-08-18 17:00:04
    String常量池问题的几个例子 示例1: Java代码  String s0="kvill";  String s1="kvill";  String s2="kv" + "ill";  System.out.println( s0==s1 );  System.out.println( s0==s2 );  结果为:  true  true...

    String常量池问题的几个例子

    示例1:

    Java代码

      String s0="kvill";

      String s1="kvill";

      String s2="kv" + "ill";

      System.out.println( s0==s1 );

      System.out.println( s0==s2 );

      结果为:

      true

      true

    分析:首先,我们要知结果为道Java 会确保一个字符串常量只有一个拷贝。

      因为例子中的 s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字 符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中” kvill”的一个引用。所以我们得出s0==s1==s2;

    示例2:

    示例:

      Java代码

      String s0="kvill";

      String s1=new String("kvill");

      String s2="kv" + new String("ill");

      System.out.println( s0==s1 );

      System.out.println( s0==s2 );

      System.out.println( s1==s2 );

      结果为:

      false

      false

      false

    分析:用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

    s0还是常量池 中"kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分 new String(”ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。

    示例3:

    Java代码

      String a = "a1";

      String b = "a" + 1;

      System.out.println((a == b)); //result = true 

           String a = "atrue";

      String b = "a" + "true";

      System.out.println((a == b)); //result = true 

            String a = "a3.4";

      String b = "a" + 3.4;

      System.out.println((a == b)); //result = true

    分析:JVM对于字符串常量的"+"号连接,将程序编译期,JVM就将常量字符串的"+"连接优化为连接后的值,拿"a" + 1来说,经编译器优化后在class中就已经是a1。在编译期其字符串常量的值就确定下来,故上面程序最终的结果都为true。

    示例4:

    Java代码

      String a = "ab";

      String bb = "b";

      String b = "a" + bb;

      System.out.println((a == b)); //result = false

    分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。

    示例5:

    Java代码

      String a = "ab";

      final String bb = "b";

      String b = "a" + bb;

      System.out.println((a == b)); //result = true

    分析:和[4]中唯一不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。

    示例6:

    Java代码

      String a = "ab";

      final String bb = getBB();

      String b = "a" + bb;

      System.out.println((a == b)); //result = false

      private static String getBB() {  return "b";   }

    分析:JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面 程序的结果为false。

     

    关于String是不可变的

           通过上面例子可以得出得知:

      String  s  =  "a" + "b" + "c";

      就等价于String s = "abc";

      String  a  =  "a";

      String  b  =  "b";

      String  c  =  "c";

      String  s  =   a  +  b  +  c;

      这个就不一样了,最终结果等于:

      Java代码

      StringBuffer temp = new StringBuffer();

      temp.append(a).append(b).append(c);

      String s = temp.toString();

      由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析,形如这样的代码:

      Java代码

      public class Test {

         public static void main(String args[]) {

           String s = null;

           for(int i = 0; i < 100; i++) {

               s += "a";

          }

       }

      }

      每做一次 + 就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后 append 字符串,如此循环直至结束。如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行 append操作。

      由于String类的immutable性质,这一说又要说很多,大家只 要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”; 就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” ” 生成 “kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的”不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原 因了,因为StringBuffer是可改变的。

     

    String中的final用法和理解

      Java代码

      final StringBuffer a = new StringBuffer("111");

      final StringBuffer b = new StringBuffer("222");

      a=b;//此句编译不通过

      final StringBuffer a = new StringBuffer("111");

      a.append("222");// 编译通过

      可见,final只对引用的"值"(即内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象 的变化,final是不负责的。

     

    总结

      栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容

      堆中存放使用new关键字创建的对象.

      字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。


    原文:http://blog.csdn.net/gaopeng0071/article/details/11741027

    展开全文
  • 常量

    千次阅读 2013-06-14 22:36:05
    1、在c中,定义常量可以使用const和#define  格式:const 类型名 常量名 = 值  格式:#define 常量名 值 2、const与类型名的顺序可以...例子如下: #include #define CLASS "zhangzetian" #define DATE 20130614
  • java String常量池问题的几个例子

    千次阅读 2014-03-27 16:22:21
    转: http://blog.csdn.net/gaopeng0071/article/details/11741027 关于string内存分配不错的博客:...String常量池问题的几个例子 示例1: Java代码  String s0=
  • java--String常量池问题的几个例子

    万次阅读 多人点赞 2013-09-16 17:05:09
    关于string内存分配不错的博客:... String常量池问题的几个例子 示例1: Java代码  String s0="kvill";  String s1="kvill";  String s2="kv" + "ill";  System.out.println
  •  #include ...输出的结果为:27 3,a只是i的一个别名,但是如果直接使用引用变量作为参数...如果你只想要传递的那个值,不想改变源对象的值,就使用 常量引用变量作为参数,这样就不会改变源对象的值。
  • 1.指针变量:指针值(即指针的指向)可以改变的指针,只能指向变量; 2.指针常量:指针值(即指针的指向)不能改变的指针,只能指向变量,但可以修改指向的实体变量的值; 3.常量指针:指向常量的指针,所以...举例子
  • 常量与符号常量

    千次阅读 2019-04-16 20:53:05
    通过“数学中的变量与常量”章节的介绍,我们知道了常量的定义,就是其数据不可以修改的量。...其内容不可改变的量,就称为常量: 100, 20, 30 这样的整数值,称为:整数型常量; 10.123, 3.14159 这样的浮点...
  • 常量指针和指针常量的区别 常量指针、指针常量以及指向常量的指针常量概念简要描述
  • 字符串常量池、class常量池和运行时常量

    万次阅读 多人点赞 2017-06-12 20:09:36
    在java的内存分配中,经常听到很多关于常量池的描述,我开始看的时候也是看的很模糊,网上五花八门的说法简直太多了,最后查阅各种资料,终于算是差不多理清了,很多网上说法都问题,笔者尝试着...
  • String int 字符串常量池 包装类型 函数参数 值传递引用传递 的 内存分配例子——源码 public static void fun_ref (Ref_test ref_out){ Ref_test ref_in=new Ref_test(); ref_in.s1="in"; //ref_out.s1=...
  • 博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留遗憾的事,做自己觉得意义的事,不浪费这大好的青春年华。博主写博客...
  • 数值常量

    千次阅读 2019-02-26 09:42:26
    常量可分为5类:它们分别是 整形常量 ... (2)实型常量 两种表示形式 第一种,由数字和小数点组成 如123.01,0.345,-32.1,0.0, 注意 .47也是 合法的 实型常量 前面的零省略未写 第二种:指数形式 如1...
  • 常量指针和指针常量

    千次阅读 2013-09-05 18:19:55
    前言 尊重版权,这篇文章是我google出来... 概述 对于新手来说,指针在c语言里总是一个非常难以理解的概念。在这篇文章中,我们将解释常量指针,指针常量,const pointer to const(ps:楼主以为这可以翻译成指向
  • 常量指针和指针常量的区别

    万次阅读 多人点赞 2018-05-24 22:57:09
    在面试中我们经常会被面试官问到什么是常量指针,什么又是指针常量。可能第一次被问到都会有些懵逼(大神略过)。...在这个例子下定义以下代码: int a,b; int * const p=&amp;amp;a //指针常...
  • 常量指针和指针常量的区别剖析

    千次阅读 2019-03-12 11:34:42
    在这个例子下定义以下代码: int a,b; int * const p=&amp;a //指针常量 //那么分为一下两种操作 *p=9;//操作成功 p=&amp;b;//操作错误 因为声明了指针常量,说明指针变量不允许修改。如同次指针指向一个...
  • 常量和const常量

    千次阅读 2018-03-03 15:12:48
    常量和const常量 标签(空格分隔): C 双学位高级语言程序设计 C算术运算和表达式 宏常量 对于那些经常使用常量,为了防止多次使用后弄错,或者忘记这个常量的含义,所以需要定义宏常量,用字符代替常量 ...
  • #include  2 int main()  3 {  4 int c;  5 int a = 2,b = 1;  6 // c = ++(a+b);... 9 原因:常量和表达式不能作为左值。... 10 a+b结果是3,为常量,不可进行自增自减预算,比如  11 i++翻
  • 数组常量

    千次阅读 2018-03-26 10:34:24
    如果数组值已经提前知道了,那么可以通过 数组常量 的方法来初始化数组,而不用依次使用 []= 方法(所有的组成元素都相同的常量语法)。 package main import "fmt" func main() { var arrKeyValue ...
  • 举个例子:现在我要在A类中引用到B类,符号引用就是我只要知道B类的全类名是什么就可以了,而不用知道B类在内存中的那个具体位置(可能B类还没有被加载进内存呢)。直接引用就相当于是一个指针,能够直接或者间接...
  • Golang 常量

    千次阅读 2020-08-03 19:24:12
    相对于变量, 常量是恒定不变的值, 经常用于定义程序运行期间不会改变的那些值. 常量的定义使用 常量的声明与变量的声明很相似, 只是把 var 换成了 const, 常量在定义的时候必须赋值. 在程序开发中, 我们用常量存储...
  • 【JVM】探究Java常量本质及三种常量

    千次阅读 多人点赞 2019-07-22 21:35:10
    总是觉得不舒服,于是就翻阅《深入理解Java虚拟机》,这本书中对常量的介绍更多地偏重于字节码文件的结构,还有在自动内存管理机制中也介绍了运行时常量池, 查阅资料后脑海中了一定的认识。 Java中的常量池分为两...
  • 关于C语言的字符常量和符号常量

    万次阅读 多人点赞 2018-11-02 21:09:48
    C语言的字符常量和符号常量符号常量字符常量 符号常量 #define指令可以把符号名定义为一个特定的字符串: #define 名字 替换文本 在该定义之后,程序中出现的所有#define中定义的名字(既没有被引号引起来,也不是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 297,720
精华内容 119,088
关键字:

常量有哪些例子