zoukankan      html  css  js  c++  java
  • 谈谈关键字new

    1.在情人节那天,无意间看到空间有人说,没有对象就new一个,然后就可以........

    程序中我们常用到X a=new X(), new在这里是创建一个对象,也可以叫做创建一个实例,我们先谈谈后半部分new X()做了什么,new X这个对象的时候,必然会调用这个类的构造方法,并且需要在堆中给对象分配内存,前半部分X a只是在栈中申明了一个内存空间,这个内存空间的类型是X,后半部分的值不可能直接赋值给a吧,如果new X()的值很大怎么办?所以a的值就是后半部分的内存的地址,也叫引用变量。所以我们搞懂了X a=new a()的后半部分是实例或者对象,前半部分是引用变量。

    2.String中的new

    我们在使用String a=“abc”类似的这种语句的时候,我们有没有想过,我们为什么不用String a=new String(),而用String a=“abc”呢?它们俩有什么区别?

    public class StringTest {
        public static void main(String[] args) {
            String str1="abc";
            String str2=new String("abc");
            String str3=null;
            str3=str1;
            
            if(str1==str2){
                System.out.println("str1和str2是一个内存空间的");
                
            }
            if(str1==str3){
                System.out.println("str1和str3是一个内存空间的");
            }
            if(str2==str3){
                System.out.println("str2和str3是一个内存空间的");
            }
            
        }
    }

    运行结果:

    str1和str3是一个内存空间的

    大家都知道==是判断对象是否为一个内存空间的。我们想想为什么运行结果是这样?

    先看看String类型的对象的产生方法:

    String有一个所谓的String constant pool ,是一个特殊的一个空间(注意这个是在PermGen上的,它是JVM用来保存类定义和常量池的保留空间,缺省是64M)保存String常量。String str = “abc”是先定义一个名为str的对String类的对象引用变量:String str;再用equals方法(String类覆盖了equals方法)判断这个特殊空间(String constant pool )是否有abc,有则将原来在栈中指向abc的引用赋值给str,否则就在这个特殊空间(String constant pool )上开辟一个存放字面值为"abc"的地址,接着在堆上创建一个新的String类的对象o,并将o 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。最后将str指向对象o的地址。

    String str2 = new String("abc"),这里"abc"本身就是pool中的一个对象,而在运行时执行new String()时,将pool中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s持有。这条语句就创建了2个String对象。它引用堆上创建的abc对象。所以str和str2是指向不同的对象,它们是不同的。那么这样话程序的运行结果就好理解了。

    结论:运行结果正好验证了我们1所提到的,使用String a="abc"相比与String a=new String("abc")更好,原因就是节省空间。

    3.new关键字牵扯的向下或者向上转型

    A.java

    public class A {
    
        public String f(A obj)
        {
            return("A");
        } 
    }

    B.java

    public class B extends A{
         public String f(B obj)
            {
                return("B");
            }
            public String f(A obj)
            {
                return("Aplus");
            } 
    
    }

    Test.java

    public class Test {
        public static void main(String[] args) {
             A a1 = new A();
             A a2 = new B(); //子类对象转化为父类,称为上转型,不需要强制转换。
             B b = new B();
             System.out.println(a2.f(b));
     
             //不会出现ClassCastException
             B b1 = (B) a2;  
             System.out.println(b1.f(b));
             System.out.println(b1.f(a1));
    
            //会出现ClassCastException
             B b2=(B) a1;
             System.out.println(b1.f(b));
             System.out.println(b1.f(a1));
             
             //父转子是危险的,这种情况会可能出现内存越界,所以向下转型需要用instanceof判断
             if (a2 instanceof B) {
                    B b1 = (B) a2;  //父类对象转化为下转型,此时需要使用强制转换,此时需要先判断要转换的这个对象(也就是a2指向的这个对象)是不是B类的实例
                    System.out.println(b1.f(b));
                    System.out.println(b1.f(a1));
                }
            } 
        
        
    
    }

    运行结果:

    Aplus
    B
    Aplus

    结论:

    向上转型:

    优点:向上转型体现了类的多态性,增强了程序的简洁性,上转型对象可以操作和使用子类继承或者重写的方法。

    缺点:上转型对象丧失了对子类新增成员变量或新增的方法的操作和使用。

    向下转型:

    给个例子,如果你说麻雀是鸟(向上转型),对的。那如果你说鸟是麻雀(向下转型),mdzz。

    4.java创建对象时, = null和new 出一个对象为空(String str=new String())的区别

    前者,是声明了一个对象(的引用),jvm并没有开辟内存放入一个对象;而后者,在声明了一个对象的引用后,又把新开辟的没有存储任何有效值的对象的地址赋给了他。

  • 相关阅读:
    题解 CF171G 【Mysterious numbers
    题解 P1157 【组合的输出】
    题解 P3955 【图书管理员】
    题解 P2036 【Perket】
    题解 CF837A 【Text Volume】
    题解 CF791A 【Bear and Big Brother】
    题解 CF747A 【Display Size】
    题解 P1332 【血色先锋队】
    题解 P2660 【zzc 种田】
    题解 P4470 【[BJWC2018]售票】
  • 原文地址:https://www.cnblogs.com/huhu1203/p/7533478.html
Copyright © 2011-2022 走看看