聊聊JAVA String类

谈起String很多人脑海中浮现出的第一印象就是:String对象是不可变的,String的底层是通过字符数组来实现的,一经初始化就不能被改变,Sting之间的比较需要通过equals()方法来实现。String类提供了很多方法来操作比如subString()取子串,charAt(int index)取指定位置的字符。但是如果对其并没有深入的认识,不仅是使用上还是面试上往往容易出错。

话不多说,先来点代码吊吊胃口:

public class StringDemo02 {
    public static void main(String [] args){
           String s1 = "a";
           String s2 = "b";
           String s3 = "ab";
           String s12 = s1+"b";
           String s4 = "a"+"b";
           String s5 = new String("ab");

           System.out.println(s3==s4);
           System.out.println(s3.equals(s5));
           System.out.println(s3==s5);       
           System.out.println(s3.equals(s4));          
           System.out.println(s12==s3);
           System.out.println(s12.equals(s3));
           System.out.println(s12==s5);
           System.out.println(s12.equals(s5));
           System.out.println(s3==s5.intern());
           System.out.println(s12==s5.intern());
           System.out.println(s3==s12.intern());
           System.out.println(s3.hashCode()==s12.hashCode());
           System.out.println(s3.hashCode()==s5.hashCode());

    }

如果上面所有的输出结果都知道,那么你对字符串的了解也应该差不多了,下面的分析也就没有看的必要了。

在说String之前先来看看Java的内存结构:
一:JAVA内存了解
JAVA主要有2个内存区域即堆和非堆,堆区按照JAVA官方的说法是运行时动态分配的区域,即所有动态分配的内存(类实列及数组)都是在这里分配出来的,但是堆区的存取速度比较慢因为他的内存管理是由GC来控制的。非堆区存放是基本类型已经对象的引用和一些JVM内部优化需要的代码,非堆中栈的存取速度很快,仅次于寄存器。比较多的说法是在堆中还有一个方法区,也有一个常量池,所有类型的常量都有一个常量池中的常量,String的常量也不例外。在常量池中保存在很多String常量对象(通常字符串时以表的形式保存,所有的常量字符保存在CONSTANT_String_info表中),因此提高了字符串的复用率,这也是JAVA这么设计的出发点。
二:常量的分类
1、静态常量池:指.class文件中的常量池,包括字符串,字面量及类的相关信息。静态常量池占用多半常量池内存。
2、动态常量池:也叫运行时常量池。及在编译的时候是不能被确定,只有等到运行时才能最终确定的。
三:实践分析
首先明确一点“==”是比较内存地址,equals比较字符串的值

    /**
    情景一
    */
        String s1 = "abc";//在常量池中创建一变了并将地址赋予s1
        String s2 = "abc";//检索到已经有“abc”直接将地址赋予s2

        System.out.println("s1==s2:"+(s1==s2));//true
        System.out.println("s1.equals(s2):"+(s1.equals(s2)));//true

第一句话在编译期间在常量池中创建一变量并将地址给s1,第二句话在常量池中检索到已经存在“abc”,所以直接将abc地址赋予s2。因此s1==s2是true;当然2个变量的内容一样的。所以s1.equals(s2)是true。整个过程只创建了一个变量。

    /**
         * 情景二
         * 在编译时会进行优化,及ab+c操作在编译时及完成
         */
        String s1 = "ab"+"c";
        String s2 = "abc";

        System.out.println("s1==s2:"+(s1==s2));//true
        System.out.println("s1.equals(s2):"+(s1.equals(s2)));//true     

因为ab+c操作在编译阶段已经完成,所以在运行的时候s1是指向常量池中的abc常量的。

        /**
         * 情景三
         * 当遇到非字面量字符串拼接时
         */
        String s1 = "ab";
        String s2 = "c";
        String s12 = s1+s2;//在编译时直接转为StringBuilder进行处理
        String s3 = "abc";

        System.out.println("s12==s3:"+(s12==s3));//false
        System.out.println("s12.equals(s3):"+(s12.equals(s3)));//true   

但JVM进行编译的时候遇到非字面时,并不能像人工一样只能计算出相应的值。所以上面的代码片段执行是先在常量池中建立以常量”ab”并赋值给s1,创建“c”常量并将地址赋给s2。JVM遇到非字面量的+处理时,自动转换为StringBulider处理,及先new一个StringBuilder变量然后append一个c形成新的字符串变量并赋值给s12。这是的s12其实是在堆区。所以s12与s3的地址肯定是不一样的。但是二者值是相同的。

/**
         * 情景四
         * 通过new产生新的对象
         */
       String s1 = new String("abc");
       String s2 = new String ("abc");
       String s3 = "abc";
       Stirng s4 = new String(s3);

        System.out.println("s1==s3:"+(s1==s3));//false
        System.out.println("s1.equals(s3):"+(s1.equals(s3)));//true
        System.out.println("s1==s2:"+(s1==s2));//false
        System.out.println("s1.equals(s2):"+(s1.equals(s2)));//true

通过new关键字都会在堆区产生新的对象,所以s1,s2,s3所表示得地址肯定是不一样的。s1,s2虽然都在堆中,但是表示不同的对象。而s3实在常量池中。但是s1,s2,s3所表示得内容都是一样的。s4虽然是用s3的内容所创建的但是也是通过new了一个新对象,所以表示地址不一样内容一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信群聊机器人一般是指在微信群中使用的聊天机器人,可以自动回复群聊中的消息,提供一些指令功能等。下面是一个简单的微信群聊机器人的Java源码示例: ```java import java.util.Date; import me.xuxiaoxiao.chatapi.wechat.WeChatClient; import me.xuxiaoxiao.chatapi.wechat.entity.contact.WXGroup; import me.xuxiaoxiao.chatapi.wechat.entity.message.WXMessage; import me.xuxiaoxiao.chatapi.wechat.entity.message.WXText; public class WeChatGroupRobot { public static void main(String[] args) throws Exception { WeChatClient client = new WeChatClient(); client.startup(); client.addListener(new WeChatClient.WeChatListener() { @Override public void onLogin() { System.out.println("登录成功"); } @Override public WXMessage onReceivingMessage(WXMessage message) { if (message instanceof WXText && message.getFromGroup() != null) { WXText textMessage = (WXText) message; String content = textMessage.getContent(); // 判断是否为指定的指令消息 if (content.equals("日期")) { String reply = "当前日期:" + new Date().toString(); client.sendText(textMessage.getFromGroup(), reply); } } return null; } }); // 进入群聊 WXGroup group = client.getGroup("群聊名称"); if (group != null) { client.syncGroup(group); } } } ``` 这段源码实现了一个简单的微信群聊机器人,当收到带有特定指令的消息时,会自动回复相应内容。在这个例子中,如果收到了"日期"指令,机器人会回复当前日期。你可以根据具体的需求自定义指令和回复内容。请注意,这是一个简化的示例,实际项目中可能需要更复杂的逻辑处理和多线程机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值