对于基本数据类型,java并没有基本数据池的概念,每次赋值并不会在栈中进行任何查询,而是直接存储值。
但是,对于基本数据类型的包装器,在一定数值范围内是存放在运行时常量池中的。
一些不靠谱的博客会混淆这个概念,认为基本数据类型在存储时首先回去看看栈中是否有该值,
如果没有则放入
30天JAVA学习第十天
引用数据类型存储的地址值含变量的数据类型
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
String字符串底层代码为char型数组,则长度一旦确定无法更改
封装性的体现:
我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)
等等
Java规定的四种不同的权限大小
1.this可以用来修饰、调用:属性、方法、构造器
2.this修饰属性和方法:
this理解为:当前对象或当前正在创建的对象
2.1在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
2.2在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法,但是,通常情况下,我们都选择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式
的使用"this.变量"的方式,表明此变量是属性,而非形参。
3. this调用构造器
3.1我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
3.2构造器中不能通过"this(形参列表)“方式调用自己
3.3如果一个类中有n个构造器,则最多有n -1构造器中使用了"this(形参列表)”
3.4规定:"this(形参列表)“必须声明在当前构造器的首行
3.5构造器内部,最多只能声明一个"this(形参列表)”,用来调用其他的构造器
import关键字
对于基本数据类型,java并没有基本数据池的概念,每次赋值并不会在栈中进行任何查询,而是直接存储值。
但是,对于基本数据类型的包装器,在一定数值范围内是存放在运行时常量池中的。一些不靠谱的博客会混淆这个概念,认为基本数据类型在存储时首先回去看看栈中是否有该值,
如果没有则放入
转载于:https://www.cnblogs.com/pw126046/p/11015268.html
一、什么是堆内存、栈内存?Java把内存划分成两种:一种是堆内存,一种是栈内存。堆:主要用于存储实例化的对象,数组。由JVM动态分配内存空间。一个JVM只有一个堆内存,线程是可以共享数据的。栈:主要用于存储局部变量和对象的引用变量,每个线程都会有一个独立的栈空间,所以线程之间是不共享数据的。在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量(变量的引用),让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。二、堆、栈的特点
- 堆:FIFO队列优先,先进先出。jvm只有一个堆区被所有线程所共享!堆存放在二级缓存中,调用对象的速度相对慢一些,生命周期由虚拟机的垃圾回收机制定。
- 栈:FILO先进后出,暂存数据的地方。每个线程都包含一个栈区!栈存放在一级缓存中,存取速度较快,“栈是限定仅在表头进行插入和删除操作的线性表”。
三、堆、栈的优缺点
- 堆的优点-可以动态的分配内存大小,生命周期不确定。缺点-速度略慢
- 栈的优点-速度快,缺点-存在栈中的数据大小和生命周期必须是明确的,缺少灵活性。
四、java中变量在内存中的分配
- 类变量(static修饰的变量):在程序加载时,系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期--一直持续到整个"系统"关闭
- 实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的"物理位置"。 实例变量的生命周期--当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存
- 局部变量:局部变量,由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放
五、直接内存
直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通脱一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
本机直接内存的分配不会受到Java 堆大小的限制,受到本机总内存大小限制
配置虚拟机参数时,不要忽略直接内存 防止出现OutOfMemoryError异常
六、直接内存(堆外内存)与堆内存比较
- 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显
- 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显
七、String赋值时,内存变化
八、更多介绍
转载于:https://www.cnblogs.com/newbie27/p/10418653.html
java学习都是从基本类型开始的,日常工作中基本类型也是经常用的东西。不过基本类型的知识点确认已经掌握了吗?
来看看那接下来的几个问题吧
1、boolean类型的长度是多少?
2、void是基本类型吗?
3、int i=0; Integer j=i;这个装箱过程中,基本类型是怎么赋值给引用类型的?
4、基本类型存储在栈上,什么时候存储在堆上呢?
这些问题的答案包含在接下来的内容里,让我们一块来研究下吧
一、什么是基本类型
Java中对象的类型分为基本类型和引用类型,那么怎么区分基本类型和引用类型呢。
常用简单区分引用类型和基本类型的方法是:基本类型存储在栈上;引用类型是引用存储在栈上,数据存储在堆上。根据数据存储位置来区分类型。这种方法实际上存在一些错误。
看下接下来的代码:
public void demo1(){int no1=0;}
no1存储在demo1方法的方法栈中,这个没有什么疑问,可是接下来的情况呢
public class Demo2 {int no2 =1;}
Demo2是引用类型,实例化对象demo2的数据存储位置是堆,no2是int类型,如果no2数据存储在栈中,demo2是如何找到栈中的no2呢,如果这里还有一个引用指向no2的引用吗?显然是不可能这么设计的,所以no2的实际存储位置是堆中。
所以,基本类型的存储位置分为这三种情况:
1、基本类型作为方法中的局部变量时,存储在方法栈上;
2、作为对象属性的时候,对象存储在堆上,那么基本类型就会存储在堆上。(这里强调对象存储在堆上,这个涉及编译优化的,暂不详述)
3、当被static或final修饰时,存储在方法区
个人观点,区分基本类型和引用类型的关键还是它们的数据存储结构,
1、基本类型数据结构组成:创建时分配的存储空间,并且存储的是基本类型包含的值;
2、引用类型的数据结构组成:栈上的引用和堆上的数据,在堆上分配的存储空间,存储的是对象的值,在栈上分配的存储空间,存储引用指向堆中的地址。
现在弄清楚了基本类型是什么,接下来具体聊一下基本类型吧
二、基本类型的分类、长度和默认值
基本类型分为四类:整形、布尔型、泛型和字符型
它们的情况如下表
其中值得研究一下的是boolean,因为官方没有明确给出boolean长度,实际的长度是由相应的虚拟机来设计的。boolean表示是、否两种情况,只需要一位就可以表示。在jvm中基本类型分为:数值类型、boolean类型和returnAddress三种类型。boolean作为一种单独的类型,个人认为它是一种比较特殊的情况。
不过在jvm中的最小单位是字节,也就是说boolean不会少于8位,比较让人接受的说法是,boolean在编译过程中使用int表示,即占用4个字节。而boolean数组中使用一个字节表示。
接下来聊一下基本类型的使用吧
三、拆箱和装箱
拆箱,即把包装类型转换为基本类型
装箱,即把基本类型转换为包装类型
拆箱和装箱是在日常代码中经常用到的,下面代码,就是一个拆箱和装箱的过程
public void demo(){//装箱Integer no1 = 10;//拆箱int no2 = no1;}
这种代码已经很熟悉了,不过no1赋值10这个过程中,一个基本类型是怎么变成引用类型的呢?
这就要从java代码的语法糖说起了
语法糖:指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。(Java中有很多被加糖的语法,如for循环、String的拼接等等,有兴趣的话可以了解下。)
也就是说Integer no1 = 10;这行代码被加糖了,具体做了什么呢。很简单反编译一下class文件看下这行代码的真实面目就好了,没有加糖前的代码是这样的
Integer no1 = Integer.valueOf(10);int no2 = no1.intValue();
这下就明白了拆箱和装箱过程的整个过程了
这里还有一个关于包装类型的比较巧妙地设计,来看下valueOf这个函数
`public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}`
IntegerCache.low 是-128,IntegerCache.hig是127,也就是说,如果int值是-128-127之间的时候,返回的结果是IntegerCache.cache这个缓存池中的对象,即valueOf函数返回结果在这个范围内的都是指向的是一个对象,如果不在这个范围内就返回一个新的Integer对象。
所以面试过程中,这个经常会问
`Integer no1 = 10;
Integer no2 = 10;
Integer no3 = 200;
Integer no4 = 200;
System.out.println(no1==no2);System.out.println(no3==no4);`
上边这块代码输出结果是什么?