java复习(一)八种基本类型与引用类型及它们的内存原理

Java 基本数据类型与引用类型

变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。

内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。

因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。

Java中有两大类型

  • 内置数据类型(基本数据类型)
  • 引用数据类型


     

    内置数据类型(基本数据类型)

    Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。

    byte:

  • byte 数据类型是8位、有符号的,以二进制补码表示的整数;
  • 最小值是 -128(-2^7),也就是一个字节;
  • 最大值是 127(2^7-1);
  • 默认值是 0;
  • byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
  • 例子:byte a = 100,byte b = -50。
  • short:

  • short 数据类型是 16 位、有符号的以二进制补码表示的整数
  • 最小值是 -32768(-2^15);
  • 最大值是 32767(2^15 - 1);
  • Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
  • 默认值是 0;
  • 例子:short s = 1000,short r = -20000。
  • int:

  • int 数据类型是32位、有符号的以二进制补码表示的整数;
  • 最小值是 -2,147,483,648(-2^31);
  • 最大值是 2,147,483,647(2^31 - 1);
  • 一般地整型变量默认为 int 类型;
  • 默认值是 0 ;
  • 例子:int a = 100000, int b = -200000。
  • long:

  • long 数据类型是 64 位、有符号的以二进制补码表示的整数;
  • 最小值是 -9,223,372,036,854,775,808(-2^63);
  • 最大值是 9,223,372,036,854,775,807(2^63 -1);
  • 这种类型主要使用在需要比较大整数的系统上;
  • 默认值是 0L;
  • 例子: long a = 100000L,Long b = -200000L。
    "L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。如果不写L就会把数据自动变为int类型。
  • float:

  • float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
  • float 在储存大型浮点数组的时候可节省内存空间;
  • 默认值是 0.0f;
  • 浮点数不能用来表示精确的值,如货币;
  • 例子:float f1 = 234.5f。
  • double:

  • double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
  • 浮点数的默认类型为double类型;
  • double类型同样不能表示精确的值,如货币;
  • 默认值是 0.0d;
  • 例子:double d1 = 123.4。
  • boolean:

  • boolean数据类型表示一位的信息;
  • 只有两个取值:true 和 false;
  • 这种类型只作为一种标志来记录 true/false 情况;
  • 默认值是 false;
  • 例子:boolean one = true。
  • char:

  • char类型是一个单一的 16 位 Unicode 字符;
  • 最小值是 \u0000(即为0);
  • 最大值是 \uffff(即为65,535);
  • char 数据类型可以储存任何字符;

例子:char letter = 'A';。

包装类:

        Java是一个面向对象的编程语言,但是Java中的八种基本数据类型却是不面向对象的,为了使用方便和解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八种基本数据类型对应的类统称为包装类(Wrapper Class),包装类均位于java.lang包。

其中,byte-》Byte;

           short->Short;

           int->Integer;

           long->Long;

           double->Double;

           float->Float;

           char->Charecter;

           boolean->Boolean;

如果要查看基本类型的范围大小,可用包装类里的Max_Value  Min_Value函数获得其边缘值,例如:System.out.println(Byte.Max_value);

补充:包装类的自动拆箱和装箱,首先解释一下概念,自动拆箱就是把包装类型自动拆为基本类型,自动装箱就是把基本类型自动包装为包装类型,例如:1.Integer integer=10;2.int  j=integer;前者就是自动装箱,后者就是自动拆箱。本质上Integer integer=99;java虚拟机编译之后,系统执行的是Integer integer=Integer.valueOf(99);int j=integer;系统为我们执行的代码是:int j=integer.valueOf();这里重点强调一下Integer.valueOf(i),这个函数,当i值在-128~127之间时,不会创建新的对象,但当i值超出这个范围就会新建一个对像,可以用==这个来判断,例如,Integer i1=100;Integer i2=100;Integer i3=200;Integer  i4=200;输出i1==i2;i3==i4;可知,前者为true,后者为false。接下来再测试一下,当Integer i1=300;int i2=300;输出

i1==i2;时,结果为true,这是因为,Integer会自动拆箱为int类型,而基本类型比较内容;


引用类型

在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。

引用类型包括类、接口、数组,装箱值类型

例子:String a=new String("adfaf"); Collection b=new ArrayList(); String[] c=new String[]{};Integer d=new Integer(46);这些都为引用类型。

  • 所有引用类型的默认值都是null。
  • 一个引用变量可以用来引用任何与之兼容的类型。

   


   最最重点:引用类型与基本数据类型在内存空间的分配;

首先介绍一下java内存中有哪些空间:可以粗浅的分为栈空间,堆空间,和方法区,

栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

 堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身

方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

下面给大家举个例子:

class Person{
  int id;
  String name;


 public void print(){

  System.out.println(id+","+name);
 } 

}
public class Test {
      public static void main(String[] args){
         Person p1=new Person();
         p1.print();
     }
}

下面这个地址是上面代码的内存图:

https://www.processon.com/view/link/5b7b7920e4b0edb75111d71e

 系统收到了我们发出的指令,启动了一个Java虚拟机进程,这个进程首先从classpath中找到Test.class文件,读取这个文件中的二进制数据,然后把Test类的类信息存放到运行时数据区的方法区中。这一过程称为Test类的加载过程。
接着,Java虚拟机定位到方法区中Test类的Main()方法的字节码,开始执行它的指令。这个main()方法的第一条语句就是:
Person p1=new Person();
语句很简单啦,就是让java虚拟机创建一个Person实例,并且呢,使引用变量p1引用这个实例。貌似小case一桩哦,就让我们来跟踪一下Java虚拟机,看看它究竟是怎么来执行这个任务的:
1、 Java虚拟机一看,不就是建立一个Test实例吗,简单,于是就直奔方法区而去,先找到Test类的类型信息再说。结果呢,嘿嘿,没找到,这会儿的方法区里还没有Person类呢。可Java虚拟机也不是一根筋的笨蛋,于是,它发扬“自己动手,丰衣足食”的作风,立马加载了Pesrson类,把Person类的类型信息存放在方法区里。
2、 好啦,资料找到了,下面就开始干活啦。Java虚拟机做的第一件事情就是在堆区中为一个新的Person实例分配内存, 这个Person实例持有着指向方法区的Person类的类型信息的引用。这里所说的引用,实际上指的是Person类的类型信息在方法区中的内存地址,其实,就是有点类似于C语言里的指针啦~~,而这个地址呢,就存放了在Person实例的数据区里。
3、在JAVA虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。OK,原理讲完了,就让我们来继续我们的跟踪行动!位于“=”前的p1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方法调用栈中。而“=”将把这个test1变量指向堆区中的Person实例,也就是说,它持有指向Person实例的引用。
OK,到这里为止呢,JAVA虚拟机就完成了这个简单语句的执行任务。参考我们的行动向导图,我们终于初步摸清了JAVA虚拟机的一点点底细了,COOL!
接下来,JAVA虚拟机将继续执行后续指令,当JAVA虚拟机执行p1.print()方法时,JAVA虚拟机根据局部变量p1持有的引用,定位到堆区中的Person实例,再根据Person实例持有的引用,定位到方法去中SPerson类的类型信息,从而获得print()方法的字节码,接着执行print()方法包含的指令。


现在我们知道了,基本数据类型就是在栈中保存,而引用类型变量在栈中,指向的对象在堆中,所以当用==比较两个变量时,一定要看清楚它是什么数据类型。点赞!!!!点赞!!!!!加关注更好哦!!!!

猜你喜欢

转载自blog.csdn.net/qq_31071255/article/details/82192075