• JavaSE Day7


    本节内容

    1.匿名对象

    2.String的实例化两种方式

    3.字符串的比较

    4.字符串常量是匿名对象

    5.String类对象两种实例化方式的区别

    6.String、StringBuffer、StringBuilder之间的关系与区别

    一、匿名对象

       .匿名对象:没有名字的实体,也就是该实体没有对应的变量名引用。

    二.匿名对象的用途

    1,当对象对方法进行一次调用的时候,可以使用匿名对象对代码进行简化。

       为什么只对方法,而不调用属性呢?因为匿名对象调用属性没意义。

       如果对象要多成员进行多次调用,必须给对象起个名字。不能在使用匿名对象。

    2,匿名对象可以实际参数进行传递。

    三.匿名对象的简单演示

    new Car().run(); 

    四.简单的例子

    需求

    将小汽车改装成3个轮子的黑车。

    1:汽车类。

    2:汽车修理厂

    * 
     匿名对象 
     匿名信 
     修黑车 
     汽车类 
     黑车厂类 
     把汽车的改成黑色3轮车。 
     
     */  
    class Car {  
        String name = "smart";  
        String color = "red";  
        int num = 4;  
      
        void run() {  
            System.out.println(name + ":" + color + ":" + num + ":跑起来了。。。。");  
        }  
      
    }  
      
    class BlackCarFactory {  
        String name;  
        String addr;  
      
        Car repairCar(Car c) {  
            c.num = 3;  
            c.color = "黑色";  
            System.out.println("改装成功啦。。。");  
              
        }  
    }  
      
    class Demo1 {  
      
        public static void main(String[] args) {  
      
            BlackCarFactory bcf = new BlackCarFactory();  
            bcf.name = "幸福修理厂";  
            bcf.addr = "天河区棠东东路御富科贸园a栋206";  
      
            // 非匿名对象  
            Car c = new Car();  
            c.run();  
            // 改装  
            bcf.repairCar(c);  
            // 取车  
            c.run();  
      
            // 匿名对象一,只使用一次:  
            // 如下创建了2个对象  
            /* 
             * new Car().run(); 
             *  
             * new Car().run(); 
             */  
      
            // 匿名对象二,作为实际参数传递  
            Car c2 = bcf.repairCar(new Car());  
            c2.run();  
      
            System.out.println();  
        }  
    }  

    1. 匿名对象设置的属性永远无法获取?  没有引用变量指向那个对象。

    2. 任何两个匿名对象使用==比较,永远返回false。

    3.  匿名对象主要应用于实参

    二、String的实例化两种方式

    1、直接赋值实例化:

    String  name="Drango war"

    以上是String对象的直接赋值,以上的代码并没有使用关键字new进行。String类也是类,所以也有构造方法

    2、使用构造方法实例化

    String  str =new String("Drango war");

    可以通过构造方法为String类对象实例化,但在构造里面依然要接收一个本类对象

    Java中的比较:   "=="的使用

    在Java中如果是基本类型的比较:

    ”==“比较的是基本类型的值。而不是内存地址。

    如果使用”==“比较的是引用数据类型,比较的是内存地址。而在String中也可以使用”==“来比较

       int a=10;
                   int b=10;
                   System.out.println(a==b);
                   String name="Drango war";
                   String name1= new String("Drango war");
                   String name2=name1;
                   System.out.println(name==name1);
                   System.out.println(name2==name1);
    
    
    
    运行结果:
    true
    false
    true

    通过以上分析可以发现,“==”比较的不是字符串对象包含的内容,而是两个对象所在的的内存对象的数值。所以“==”属于数值比较,比较的是内存地址。

    如果想比较字符串的内容,可以使用String类的equals()方法。

     
                   String name="Drango war";
                   String name1= new String("Drango war");
                   String name2=name1;
                   System.out.println( name.equals(name1));
                   System.out.println(name2.equals(name1));
    
    
    运行结果
    
    true
    true

    于是,现在比较的不是字符串的内存地址的数值,而是字符串的内容。

    小结:
    (1) ==:比较的是两个字符串内存地址的数值是否相等,属于数值比较;
    (2)equals():比较的是两个字符串的内容,属于内容比较。

    三、字符串常量是匿名对象

    在各个语言中并没有提供字符串的数据类型定义,很多语言都是使用字符数组来描述字符串的概念,在Java中也没有字符串的概念,只是Java自己做了简单处理。但是在Java中字符串依然不属于基本数据类型,字符串是作为String类的匿名对象的形式存在的。

    String name="Drango war";
                 
    System.out.println("Drango war".equals(name));
    
    
    运行结果:
    
    true

    匿名对象可以调用类中的方法与属性,而以上的字符串调用了equals()方法,所以它一定是一个对象。

    四、String类对象两种实例化方式的区别

    1、直接赋值的实例化方式:

     String str = "Hello" ;

    此时,只分配了一块堆内存空间和一块栈内存空间:

    String str1 = "Hello" ;
    String str2 = "Hello" ;
    String str3 = "Hello" ;
    System.out.println(str1 == str2) ;
    System.out.println(str1 == str3) ;
    System.out.println(str2 == str3) ;
    
    运行结果
    
    true
    true
    true

    我们发现以上所有直接赋值的String类对象的内存地址完全相同,内存分配图如下:

    在设计String类的时候采用了一种称为共享设计模式的概念。在运行的JVM底层存在一个字符串的对象池(Object Pool),如果用户采用了直接赋值的方式时,会将字符串的内容放入池保存,如果以后其他String对象继续使用直接赋值方式实例化,并且设置了同样的内容时,那么将不会分配新的堆内存空间,而是使用已有对象的引用进行分配继续使用。如果新声明的字符串内容不在对象池中,则会分配一个新的,然后继续放到池中以供下次使用。

    2、采用构造方法实例化的方式:

    使用构造方法实例化一定要用到new关键字,而一旦使用了new就表示要分配新的内存空间。

    String str = new String("Hello") ;

    从上可以发现,分配了两块堆内存空间,其中一块是垃圾。这样处理内存的浪费外,使用构造方法定义的String类对象,其内容不会保存在对象中(因为重新分配了新的一块堆内存)。

    现在希望使用构造方法定义的String类对象,其内容要保存在对象中,该怎么办么?我们可以使用String类定义的一个手工入池的方法:

    public String intern()

    小结:String类对象两种实例化的区别?
    (1)直接赋值实例化方式(String str = “xxx”):只会分配一块堆内存空间,并且对象内容自动入池,以供重复使用;
    (2)构造方法实例化方式(String str = new String(“xxx”)):会分配两块堆内存空间,其中有一块是垃圾,并且不会自动入池,用户可以使用intern()方法手动入池。

    String、StringBuffer、StringBuilder之间的关系与区别

    1.可变与不可变

    1)String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

     private final char value[];

    String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。

    2)StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。

    StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。

    StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类

    2.是否多线程安全

    String中的对象是不可变的,也就可以理解为常量,显然线程安全

    AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

    StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的

    StringBuilder并没有对方法进行加同步锁,所以是非线程安全的

     3.StringBuffer和StringBuilder类的速度比较

    一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种比较是相对的,不是绝对的。(要考虑程序是单线程还是多线程)

    不考虑多线程,采用String对象时,执行时间比其他两个都要高得多,而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显;而以String类为例,操作字符串对象引用相加类型使用的时间比直接/操作字符串相加使用的时间也多得多。由此可见,如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;如果要保证线程安全,自然是StringBuffer;能直接操作字符串不用字符串引用就直接操作字符串。

  • 相关阅读:
    php 通过二维码图片读取二维码内容
    Centos 文件系统 xfs、ext4、ext3 的区别
    js 实现省市县三级联动
    Scrapy 爬虫实战
    Mongodb 和 MySql native json 对比
    Vite —— 一种新的、更快地 web 开发工具
    解决mysql for docker容器报错:Authentication plugin 'caching_sha2_password' cannot be loaded
    Spring boot 自定义注解,Java通过反射获取注解,及注解的说明,附源码下载!
    Spring boot 自定义注解+@Aspect实现切面输出日志,附源码下载!
    HTML5 Canvas基础教程
  • 原文地址:https://www.cnblogs.com/wuzhilong/p/9377946.html
Copyright © 2020-2023  润新知