JAVA中的指针
不同于CPP,JAVA中不需要程序员对指针进行操作。不过,这不代表JAVA没有指针,事实上,JAVA的指针操作都被底层代码封装了。笔者在初学Java时,虽然就了解了形参,实参,StringBuffer这些概念,但一直只流于表面,对此没有一个深度的认识。直到最近开始学习JVM虚拟机,才真正认识到了JAVA的精妙之处。
首先,先说结论,Java中所有的基本数据类型的传递,都是按值传递,即传递的都是形参。除此以外的其他任何传递都是按地址传递,传递过去的都是实参,即cpp概念中的引用传递。最初笔者学习时也是就看到这,虽然知道了结论,但由于概念过于抽象,始终无法理解其本源(或者说内存模型中到底发生了什么)。Talk is cheap,show me the code。下面,我们来看一段代码。
package point;
public class Formal {
private void formal(int p){
p=p*5;
System.out.println(p);
}
public static void main(String[]args){
int i=5;
Formal fromal=new Formal();
fromal.formal(i);
System.out.println(i);
}
}
这段代码在控制台输出的结果是25和5,很显然,按照正常的逻辑来说的话应该是25,25才对。为什么会出现这种结果?事实上,Java中对基本数据类型的传递都是值传递(不清楚为什么这样,笔者的理解是基本数据类型在内存中的组合是有限的,这样内存可以知道你需要传递的是什么,换而言之,它可以真正理解你要传递的东西,因此可以复制一份进行传递,这样虽然会增大程序员的学习成本,但可以节省内存或者是增进效率。而非基本数据类型因为变化太多了,所以无法这么操作。不知道本人的理解有没有误差,才疏学浅,希望大神们多多指正)。通俗一点说,就是复制操作,在内存中,JVM只是把你操作的数据复制了一份给你传递到的对象,而不是把它本身传递了过去。
这里要说一个特例,String类,贴一段代码。
package point;
public class ActualString {
private void actual(String color){
color=color+" is red";
System.out.println(color);
}
public static void main(String[]args){
String car="myCar";
ActualString actualString =new ActualString();
actualString.actual(car);
System.out.println(car);
}
}
这里控制台输出结果是myCar is red,myCar,这不代表String传递的也是形参,或者是String是基本数据类型,事实上因为String类都是被final关键字修饰的,所以它的值不会变化,所以,字符串拼接之类的操作事实上只是在内存中开辟了一个新的空间,而原有的空间其实还存在,所以这就是为什么字符串的操作要使用StringBuffer类。
下面我们看一下实参的代码。
package point;
public class Actual {
private void actual(int arr[]){
arr[0]=arr[0]*5;
System.out.println(arr[0]);
}
public static void main(String[]args){
int a[]=new int[]{5};
Actual actual=new Actual();
actual.actual(a);
System.out.println(a[0]);
}
}
毫无疑问,这次控制台输出的结果是25,25。这里传递的就是对象本身的地址值,即实参,可以理解为剪切操作,将自身传递过去。
package point;
class Variable{
public static Variable VAR=null;
public int i;
protected void a(int p){
p=p*5;
System.out.println(p);
}
public Variable(){
i=5;
Variable.VAR=this;
}
}
public class FormalInActual {
public static void main(String[] args){
Variable variable=new Variable();
System.out.println(variable.i);
variable.a(variable.VAR.i);
System.out.println(variable.VAR.i);
}
}
输出结果是5,25,5。即使是像这样把基本数据类型写进方法里,通过方法传递,其传递的依旧是形参。
JAVA中的指针的更多相关文章
- 【实战Java高并发程序设计 1】Java中的指针:Unsafe类
是<实战Java高并发程序设计>第4章的几点. 如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现.现在,就让我 ...
- java中的“指针”
java中的"指针" 通常我们说java中没有指针,但是java中的"引用"就相当于指针,只是不称为指针而已. 错误例子 public List<Clus ...
- 4.4.3 Java中的指针:Unsafe类
java多线程编程的无锁CAS底层都是通过 Unsafe进行操作的:源码如下 public final boolean compareAndSet(int expect, int update) { ...
- Java中到底有没有指针;同时注意引用和指针的区别
Java中引用的作用类似于指针,但是有区别:() (1) 指针必然指向一个内存地址,如果你定义的时候不指定,就会乱指(很可能造成安全隐患)但是引用定义出来后默认指向为空. (2) 指针可 ...
- java中传值及引伸深度克隆的思考(说白了Java只能传递对象指针)
java中传值及引伸深度克隆的思考 大家都知道java中没有指针.难道java真的没有指针吗?句柄是什么?变量地址在哪里?没有地址的话简直不可想象! java中内存的分配方式有两种,一种是在堆中分配, ...
- 使用java实现单链表----(java中的引用就是指针)
//一直以为java中没有指针,其实java的引用就是指针,只不过堆栈中的引用储存了在堆中的地址,可以看做java中的指针.public class sibgleLink<E> { // ...
- Java中堆内存和栈内存详解2
Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...
- Java中的堆栈区别
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...
- java中内存分配策略及堆和栈的比较
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
随机推荐
- 【快学springboot】9.使用 @Transactional 注解配置事务管理
介绍 springboot对数据库事务的使用非常的方便,只需要在方法上添加@Transactional注解即可.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的 ...
- Dubbo+zookeeper部署到tomcat上注意事项,遇到的问题,闪退,运行报错等
需要下载工具zookeeper-3.4.14.tar.gz,dubbo-2.5.x.zip,apache-tomcat-8.5.47-windows-x64.zip这些官网都可以先下载到 1.最新的z ...
- QQ企业通知识点---ClassSerializers
Serializers 串列器 序列化器 串行器 MemoryStream 创建其支持存储区为内存的流. BinaryFormatter 以二进制格式将对象或整个连接对象图形序列化和反序列化 ...
- LeetCode206. Reverse Linked List(反转链表)
题目链接:https://leetcode.com/problems/reverse-linked-list/ 方法一:迭代反转 https://blog.csdn.net/qq_17550379/a ...
- mysql视图初探
mysql视图初探 官方例子如下,从官方的例子就可以看出来视图就是提供一种快捷查询.用视图来查询一些常用的结果. mysql> help create view; Name: 'CREATE V ...
- Linux centosVMware 磁盘格式化、磁盘挂载、手动增加swap空间
一.磁盘格式化 磁盘分区后不能直接使用,需要对每一个分区格式化,格式化其实就是安装系统文件. 命令mke2fs:不支持格式化成xfs系统文件 mkfs.ext4 == mke2fs -t ext4 ...
- 6专题总结-动态规划dynamic programming
专题6--动态规划 1.动态规划基础知识 什么情况下可能是动态规划?满足下面三个条件之一:1. Maximum/Minimum -- 最大最小,最长,最短:写程序一般有max/min.2. Yes/N ...
- sklearn实现多分类逻辑回归
sklearn实现多分类逻辑回归 #二分类逻辑回归算法改造适用于多分类问题1.对于逻辑回归算法主要是用回归的算法解决分类的问题,它只能解决二分类的问题,不过经过一定的改造便可以进行多分类问题,主要的改 ...
- 性能测试中TPS上不去的几种原因
性能测试中TPS上不去的几种原因 什么叫TPS: TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为 ...
- Swift 语法糖then
then是一个swift初始化库,只有80几行的代码库,确可以让初始化变得很优雅. 1.使用then初始化AnyObject,这里以初始化控件为例 lazy var label = UILabel() ...