基本数据类型vs对象类型


基本数据类型vs对象类型

当你阅读这篇文章的时候,可能已经知道了Java是双类型的系统,也就是基本数据类型和对象类型,简称基本类型和对象。Java中有8个预定义的基本类型,它们的名字都是保留的关键字。常见的基本类型有int、double和boolean。Java中所有其他的类型包括用户自定义的类型,它们必然也是对象类型(我说”必然”是因为数组类型有点例外,与基本类型比数组更像是对象类型)。每一个基本类型都有一个对应的对象包装类,比如int的包装类是Integer,double的包装类是Double,boolean的包装类是Boolean。

基本类型基于值,而对象类型则基于引用。与基本类型相关的争议都源于此。为了说明它们的不同,先来看一下两个声明语句。第一个语句使用的是基本类型,第二个使用的是包装类。

int n1 = 100;

Integer n2 = new Integer(100);

使用新添加到JDK5的特性自动装箱以后,第二个声明可以简化成:

Integer n2 = 100;

但是,底层的语义并没有发生改变。自动装箱简化了包装类的使用,减少了程序员的编码量,但是对运行时并没有任何的改变。

图1展示了基本类型n1和包装对象类型n2的区别。

n1持有一个整数的值,但是n2持有的是对一个对象的引用,即那个对象持有整数的值。除此之外,n2引用的对象也包含了一个对Double对象的引用。

内存的使用

Java中的double总是占据内存的64个比特,但是引用类型的字节数取决于JVM。我的电脑运行64位Win7和64位JVM,因此在我的电脑上一个引用占用64个比特。根据图1,一个double比如n1要占用8个字节(64比特),一个Double比如n2要占用24个字节——对象的引用占8个字节,对象中的double的值占8个字节,对象中对Double对象的引用占8个字节。此外,Java需要使用额外的内存来支持对象的垃圾回收,但是基本类型不需要。

package mytest;

import java.util.Date;

public class Test {
/**
 * @param n 矩阵n*n
 * @param type 类型 1:double 2:Double
 * @return 获得存储所使用的字节数
 */
    public static long getBytesUsingPrimitives(int n,int type){

      System.gc();// force garbage collection
      long memStart = Runtime.getRuntime().freeMemory();
      // put some random values in the matrix
      switch(type){
          case 1:
              double[][] a = new double[n][n];
              for (int i = 0;  i < n;  ++i){
                  for (int j = 0; j < n;  ++j)
                      a[i][j] = Math.random();
                }
              break;
          case 2:
              Double[][] ax=new Double[n][n];
              for (int i = 0;  i < n;  ++i){
                  for (int j = 0; j < n;  ++j)
                      ax[i][j] = Math.random();
                }
              break;
          default:
              break;
      }

      long memEnd = Runtime.getRuntime().freeMemory();

      return memStart - memEnd;
    }
    
    
    //创建double类型矩阵n*m
    public static double[][] create(int n,int m){
        double[][] a = new double[n][m];
        for (int i = 0;  i < n;  ++i){
            for (int j = 0; j < n;  ++j)
                a[i][j] = Math.random();
          }
        return a;
    }
    //创建Double类型矩阵n*m
    public static Double[][] createD(int n,int m){
        Double[][] a=new Double[n][n];
        for (int i = 0;  i < n;  ++i){
            for (int j = 0; j < n;  ++j)
                a[i][j] = Math.random();
          }
        return a;
    }
    /**
     * 创建矩阵,并使两个矩阵相乘
     * 返回 运行时长
     */
    public static long multiply(int x1,int y1,int x2,int y2,int type){
        Date d1=null;
        switch(type){
        case 1:
            double[][] a=create(x1,y1);
            double[][] b=create(x2,y2);
            d1=new Date();
            if (!checkArgs(y1, x2))
                throw new IllegalArgumentException("Matrices not compatible for multiplication");
            
            int nRows = a.length;
            int nCols = b[0].length;

            double[][] result = new double[nRows][nCols];

            for (int rowNum = 0;  rowNum < nRows;  ++rowNum){
                for (int colNum = 0;  colNum < nCols;  ++colNum){
                        double sum = 0.0;

                        for (int i = 0;  i < a[0].length;  ++i)
                            sum += a[rowNum][i]*b[i][colNum];

                        result[rowNum][colNum] = sum;
                  }
              }
            break;

        case 2:
            Double[][] ax=createD(x1,y1);
            Double[][] bx=createD(x2,y2);
            d1=new Date();
            if (!checkArgs(y1, x2))
                throw new IllegalArgumentException("Matrices not compatible for multiplication");
            
            int nRowsx = ax.length;
            int nColsx = bx[0].length;

            Double[][] resultx = new Double[nRowsx][nColsx];

            for (int rowNum = 0;  rowNum < nRowsx;  ++rowNum){
                for (int colNum = 0;  colNum < nColsx;  ++colNum){
                        Double sum = 0.0;

                        for (int i = 0;  i < ax[0].length;  ++i)
                            sum += ax[rowNum][i]*bx[i][colNum];

                        resultx[rowNum][colNum] = sum;
                  }
              }
            break;
            default:
                break;

        }

      Date d2=new Date();
      return d2.getTime()-d1.getTime();
    }
    

    private static boolean checkArgs(int y1, int x2) {
        if(y1!=x2)
            return false;
        
        return true;
    }
    
    public static void main(String[] args){
        //运行结果,并不是保持不变,这里是平均值
        System.out.println(getBytesUsingPrimitives(1000, 1));//字节数统计    7585424
        System.out.println(getBytesUsingPrimitives(1000, 2));//         28646800

        System.out.println(multiply(1000,1000,1000,1000,1));//所用时间 12773
        System.out.println(multiply(1000,1000,1000,1000,2));//      39017
    }

}

  

优质内容筛选与推荐>>
1、angular弹出层实现
2、SpringBoot标签之@ConfigurationProperties、@PropertySource注解的使用
3、微信支付功能
4、廖雪峰py笔记8函数的参数
5、C++多态性的总结


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号