Code Monkey home page Code Monkey logo

blog's People

Contributors

septillions avatar

Watchers

 avatar

blog's Issues

书单

步履不停

author: 是枝裕和
published: 2017-05-01
progress: 正在阅读
score: 8.7
rating: 4
cover: //raw.githubusercontent.com/septillions/pic/master/book/步履不停.jpg
description: 人生路上,步履不停,总有那么一点来不及。活着,是多么的麻烦,多么的有趣,多么的悲伤啊。同时,又是多么美丽的一件事啊。

杀死一只知更鸟

author: 哈珀·李
published: 2017-02-01
progress: 正在阅读
score: 9.2
rating: 5
cover: //raw.githubusercontent.com/septillions/pic/master/book/杀死一只知更鸟.jpg
description: 如何在充满丑陋与问题的世界中塑造自己的道德底线。在复杂的社会中,哪些方面应该去适应去顺应,哪些方面应该坚持自己的立场,哪怕要为此付出代价。

代码整洁之道

author: Robert C·Martin
published: 2010-01-01
progress: 已阅读
score: 8.6
rating: 5
cover: //raw.githubusercontent.com/septillions/pic/master/book/代码整洁之道.jpg
description: 代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。本书作者给出了一系列行之有效的整洁代码操作实践。

Effective Java

author: Joshua Bloch
published: 2018-12-11
progress: 温习中
score: 9.1
rating: 5
cover: //raw.githubusercontent.com/septillions/pic/master/book/Effective_Java.jpg
description: 本书一共包含 90 个条目,每个条目讨论 Java 程序设计中的一条规则。这些规则反映了最有经验的优秀程序员在实践中常用的一些有益的做法。

友链

樱花庄的白猫

link: //2heng.xin
cover: //i.loli.net/2019/10/07/UAneVdf5uHzv2Bs.jpg
avatar: //i.loli.net/2019/10/07/vRBDZKiCaAVctHz.jpg

水八口记

link: //blog.shuiba.co
cover: //i.loli.net/2019/10/07/cbIPTgof9zAkBi6.jpg
avatar: //i.loli.net/2019/10/07/HxDjfKBorST2G5L.jpg

Relex

link: //relex.me
cover: //i.loli.net/2019/10/07/nSuIxGpsc3JFk97.jpg
avatar: //i.loli.net/2019/10/07/hmH3M6xzkuGVb1f.jpg

关于

Summary

思绪来得快去得也快,偶尔会在这里停留。

目前还没什么其他可说的,如果你也是 Gamer 欢迎一起玩。

Nintendo Switch FC : SW-3321-2246-3632

PlayStation Network : PS_Eolinker

Theme

如你所见,现在呈现在你眼前的是一个基于 Vue 开发的 SPA 单页面博客应用程序,后台数据源依托于 Github Issues,借助 Github Api 获取数据。此外,还使用开源项目 Gitalk 作为博客的评论系统,基本上使用了 Github 全家桶。充分利用 Github 开源的免费服务,脱离服务器与数据库,关注内容本身。

技术栈:Vue + Github Issues + Gitalk。

Timeline

2022-07-15:托管到 Vercel 提升国内访问速度
2022-04-25:更换域名 loiter.me
2019-10-07:网站正式上线
2019-09-08:购入域名 septillion.me

Java 中的类型传递问题解惑

我之前一直犯了一个错误,认为 Java 中是有引用传递的,其实不然,写这篇文章一方面是纠正自己的理解,另一个是希望看到文章的人不要犯同样的错。

类型传递有什么蹊跷?

要讨论 Java 中是值传递还是引用传递,先来看看如何定义值传递和引用传递。

  • 值传递(pass by value):在调用函数时将实际参数拷贝一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
  • 引用传递(pass by reference):在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

它们都是在发生函数调用时的一种参数求值策略,这是对调用函数时,求值和传值的方式的描述,而非传递的内容类型(内容指:是值类型还是引用类型,是值还是指针)。值类型/引用类型,是用于区分两种内存分配方式,值类型在栈上分配,引用类型在堆上分配。一个描述内存分配方式,一个描述参数求值策略,两者之间无任何依赖或约束关系。下面通过一些代码来理解这些话。

Java 代码的味道

在 Java 中有基本类型如 intbooleanchar,也有对象类型如 ObjectHashMapInteger 等。

最简单的例子

public static void swap(int a, int b) {
    int x = a;
    a = b;
    b = x;
    System.out.println("swap a: " + a);
    System.out.println("swap b: " + b);
}

public static void main(String[] args) {
    int a = 3;
    int b = 4;
    swap(a, b);
    System.out.println("a = " + a);
    System.out.println("b = " + b);
}

对于这段代码的输出是:

swap a: 4
swap b: 3
a = 3
b = 4

int 是一个基本类型,我们将 2 个变量的值传入到 swap 方法中,它们实际的结构是这样的:

swap

引用类型的例子

static class Foo {
    String name;

    public Foo(String name) {
        this.name = name;
    }
}

static void change(Foo myfoo) {
    System.out.println("change input myfoo.name: " + myfoo.name);

    myfoo.name = "FiFi";
    System.out.println("change new   myfoo.name: " + myfoo.name);
}

public static void main(String[] args) {
    Foo foo = new Foo("Jerry");
    change(foo);

    System.out.println(foo.name);
}

对于这样一段代码的输出是:

change input myfoo.name: Jerry
change new   myfoo.name: FiFi
FiFi

对于 change 方法接收到的 name 是 Jerry 我们可以理解,修改后方法内输出的 FiFi 也可以理解,因为在同一函数体内,变量的修改必然是可见的。需要解释的就是外部的修改也会发生变化,这是为啥呢?

change

看了这幅图你大概就明白了,我们 new Foo("Jerry") 这句话会在堆上开辟一块内存空间,假设叫它 0xabcd 好了,把这块内存赋值给一个名为 foo 的引用类型。进入 change 方法的时候就会传递一份 foo 引用类型的拷贝(参数入栈),我故意把这个变量名写为 myfoo 防止大家理解错误,myfoofoo 这 2 个引用类型都指向同一块堆内存空间,在 change 方法内通过 myfoo 修改的值也会影响到其他指向这块内存的引用类型。

结论:对于引用类型,是通过传值的方式传引用(引用类型)。这句话可能会有点儿绕,不要死记硬背它。

上面的例子都是演示了 Java 中的值传递,假设 Java 里有引用传递会是什么样子呢?来看看这段代码

static void change(Foo myfoo) {
    System.out.println("change input myfoo.name: " + myfoo.name);

    // 改变 foo 的指向,让它指向一个新的内存
    myfoo = new Foo("Tom");
    System.out.println("change new   myfoo.name: " + myfoo.name);
}

public static void main(String[] args) {
    Foo foo = new Foo("Jerry");
    change(foo);

    System.out.println(foo.name);
}

这段代码的输出是:

change input myfoo.name: Jerry
change new   myfoo.name: Tom
Jerry

可能你看到这里已经恍然大悟了,如果 Java 中可以传递引用意味着 myfoo = new Foo("Tom"); 这行代码的修改会影响到之前的 foo 变量,会让 foomyfoo 指向同一块新的地址,然后导致外部的 foo.name 会输出 Tom。

我们看到结果不是这样的,正因为是传值(拷贝了一份)。这行代码会创建一个新对象,让 myfoo 指向新内存,而 foo 指向的还是旧的内存,所以 myfoo 的是不会影响到外部的。

新疑问

看到上面其实值传递的概念和理解已经比较清晰了,之前又遇到一个问题,来看看代码吧

static void change(Integer num) {
    System.out.println("change input num: " + num);
    num = 2333;
    System.out.println("change new   num: " + num);
}

public static void main(String[] args) {
    Integer num = 1;

    change(num);
    System.out.println(num);
}

我当时的疑问,Integer 是引用类型吗?传递给 change 方法的参数修改后会影响外部吗?

  • Integer 创建出来的是一个对象(自动装箱),所以是引用类型
  • 不会影响到外部

第二个问题为什么就不会影响到外部呢?原因是这样的,Integer 这个类(还有 StringDoubleLong 等)比较特殊,它是 final 的,是不可变的。当我们使用 num = 2333; 这行代码去赋值的时候发生了什么?

这里我就不画图描述了,这行代码意味着给 num 又创建一个新的对象,所以方法内的 num 引用类型指向了 2333 所处的内存。当我们使用 = 进行操作时候修改的是引用,而不是一个单纯的赋值操作,相当于前面例子中的 myfoo = new Foo("Tom")。如果你想实现 Integer 数值的修改可以试试 AtomicInteger 这个类。

小结

  • 一个方法不能修改一个基本数据类型的参数
  • 一个方法可以修改一个对象参数的状态
  • 一个方法不能实现让对象参数引用一个新对象

之前对 Java 中值传递理解不够的原因是没有分清 引用引用传递 是什么,只是在 Java 中理解起来有点绕,通过上面的小示例分析了这些问题出现的原因,如果你还有些模糊也可以参考我下方给出的链接学习,有什么疑问可以留言告诉我。

参考

Life

不追名逐利恬淡的过一生。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.