Blog of Woo

  • 首页

  • 标签

  • 归档

  • 公益 404

  • 搜索

为什么匿名内部类访问局部变量必须是final?

发表于 2018-11-02 | 更新于 2019-02-19 | 评论数: | 阅读次数:
本文字数: 4.1k | 阅读时长 ≈ 4 分钟

一个谜团

如果你用过类似 guava 这种 “伪函数式编程” 风格的 library 的话,那下面这种风格的代码对你来说应该不陌生:

1
2
3
4
5
6
7
8
9
public void tryUsingGuava() {
final int expectedLength = 4;
Iterables.filter(Lists.newArrayList("123", "1234"), new Predicate<String>() {
@Override
public boolean apply(String str) {
return str.length() == expectedLength;
}
});
}
阅读全文 »

既然Java反射可以访问和修改私有成员变量,那封装成private还有意义么?

发表于 2018-11-02 | 更新于 2019-02-18 | 评论数: | 阅读次数:
本文字数: 1.7k | 阅读时长 ≈ 2 分钟

既然Java反射可以访问和修改私有成员变量,那封装成private还有意义么?

简单来说,private并不是解决“安全”问题的。
安全是指不让代码被非法看到/访问。但是只要人能拿到代码,总会有办法去查看和改变代码。
其他答案提到反射可以用SecurityManager来防止private被访问。但是从更高一层的角度,即便使用了SecurityManager,还是可以通过各种方式拿到java的bytecode,并做任意修改。比如有asm这样的lib,也有instrument api这种东西可以帮你。
所以记得,如果你真有一段代码不允许被别人看/用,就不要把这段代码放到其他人可以碰到的地方,而是做一个server,通过接口允许有限制的访问。其他人想破解,只能破解你的服务器网关和跳板机器。
关于真正的安全性,可以参考激活服务器的工作原理.
private想表达的不是“安全性”的意思,而是OOP的封装概念,是一种编译器可以帮助你的设计上的hint。这就像是一家没人的店挂了个牌子“闲人免进”,但你真要进去还是有各种办法可以办到。所以private,以及所有其他的access modifier都有一层隐含的含义:如果你按照遵守这套规则,开发者可以保证不问题(不考虑bug的情况下);否则,后果自负。比如,你在用spring的IoC的时候,你知道你要“注入”,不管它是不是private的,你知道“注入”是你自己控制的,是你设计好的效果。那么通过spring的IoC利用反射帮你注入一些private property是再正常不过的用法。再比如,单元测试,你就想测一个private方法。但是因为private的缘故就是测不了。于是你可以用反射绕开这个限制,开心的做测试。虽说某些人坚持“不应该测试private方法,而应该通过测试其他方法间接测试private方法,但并没有形成广泛的共识。这里不对这个问题展开。虽然能绕开,但绕开的代码很繁琐。久而久之就会厌倦。毕竟,代码应该为你工作,而不是你为代码工作。
因此,我的经验是通常会用protected或者default来代替private。我曾设想runtime应该给一种运行模式,通过设定一个启动参数使其不管private这类的限制,这样做UT,做profiling等工作都会轻松许多。等到最后发布时,再用普通模式。但可惜现实当中并没有这种设定。评论区提到了Android里的VisibleForTesting,可以实现我期望的功能。大赞!感谢 @尤华杰
我之所以敢用protected/default来代替private是因为现实当中非private不可的情景非常少见。实际上,很多时候private带来的麻烦比起带来的好处要多,这是因为很多时候对OOP的误用造成的。OOP的误用造成了无谓的private,然后逼着你必须得绕开private。其实private就是个约定而已。
看看其他语言,比如python,它的“private“是一种很松散的约定,所有private的成员都用下划线开头,告诉调用者“不要随便调用我哦”,但是如果真调用了也就调用了。C++,通过指针就能绕开private。
有人说,private会避免新手误用。但问题是,大家从出道开始,自己或者周围的同事朋友有谁曾经出过这个问题?IDE知道一个成员当前不能访问,就根本就不会提示。如果一个人已经开始通过源代码/反编译研究“我能不能调用这个私有方法了“,他还算是一个菜鸟吗?他会不知道这里的潜在风险吗?如果真的误用了,code review能过吗?测试能过吗?如果一个公司因为误用private成员,造成了重大的损失,那这个公司就活该倒闭算了,不要在世上丢人。
OOP是一种编程思想,是众多编程思想中的一种。是开发者决定了一个问题应该用OOP合适,并且用了Java这样的语言来简化自己开发OOP代码时的工作。如果抱着这种态度,就不会误用,因为private在开发者的心中。其他人也不太可能误用,如果他上过几天java培训。不要因为语言是OOP的就去套,把不适合的OOP的代码强用OOP的各种套路实现,然后给自己后续的维护扩展埋坑。

如何优雅的使用和理解线程池

发表于 2018-11-02 | 更新于 2019-02-19 | 评论数: | 阅读次数:
本文字数: 6.9k | 阅读时长 ≈ 6 分钟

前言

平时接触过多线程开发的童鞋应该都或多或少了解过线程池,之前发布的《阿里巴巴 Java 手册》里也有一条:

可见线程池的重要性。

简单来说使用线程池有以下几个目的:

  • 线程是稀缺资源,不能频繁的创建。
  • 解耦作用;线程的创建于执行完全分开,方便维护。
  • 应当将其放入一个池子中,可以给其他任务进行复用。
阅读全文 »

理解B树,B+树特点及使用场景

发表于 2018-11-02 | 更新于 2019-02-18 | 评论数: | 阅读次数:
本文字数: 3.7k | 阅读时长 ≈ 3 分钟

读完本文你将了解:

  • B 树
    • 对比平衡二叉树和 B 树
    • B 树中如何查找数据
    • B 树如何保证平衡
    • 使用场景
  • B+ 树
  • Thanks

大家好,前面那篇文章《3 分钟理解完全二叉树、平衡二叉树、二叉查找树》中我们了解了几种特殊的二叉树的功能及特点,知道了它们在进行查找数据时可以提高效率,但需要注意的是,这是指在内存中进行查找。如果有海量的数据,不可能一次性读取到内存中,这时候就要考虑的是,如何在磁盘中快速找到需要的数据。

今天这篇文章中要介绍的 “B 树、B+ 树”,他们的使用场景是:查找磁盘中的大量数据。

阅读全文 »

类加载器与双亲委派模型

发表于 2018-11-02 | 更新于 2019-02-19 | 评论数: | 阅读次数:
本文字数: 5.5k | 阅读时长 ≈ 5 分钟

类加载器

加载类的开放性

类加载器(ClassLoader)是 Java 语言的一项创新,也是 Java 流行的一个重要原因。在类加载的第一阶段 “加载” 过程中,需要通过一个类的全限定名来获取定义此类的二进制字节流,完成这个动作的代码块就是类加载器。这一动作是放在 Java 虚拟机外部去实现的,以便让应用程序自己决定如何获取所需的类。

虚拟机规范并没有指明二进制字节流要从一个 Class 文件获取,或者说根本没有指明从哪里获取、怎样获取。这种开放使得 Java 在很多领域得到充分运用,例如:

  • 从 ZIP 包中读取,这很常见,成为 JAR,EAR,WAR 格式的基础
  • 从网络中获取,最典型的应用就是 Applet
  • 运行时计算生成,最典型的是动态代理技术,在 java.lang.reflect.Proxy 中,就是用了 ProxyGenerator.generateProxyClass 来为特定接口生成形式为 “*$Proxy” 的代理类的二进制字节流
  • 有其他文件生成,最典型的 JSP 应用,由 JSP 文件生成对应的 Class 类
    ……
阅读全文 »

CPU100%问题定位实战

发表于 2018-11-02 | 更新于 2019-02-18 | 评论数: | 阅读次数:
本文字数: 777 | 阅读时长 ≈ 1 分钟

功能问题,通过日志,单步调试相对比较好定位。
性能问题,例如线上服务器 CPU100%,如何找到相关服务,如何定位问题代码,更考验技术人的功底
题目 某服务器上部署了若干 tomcat 实例,即若干垂直切分的 Java 站点服务,以及若干 Java 微服务,突然收到运维的 CPU 异常告警
问:如何定位是哪个服务进程导致 CPU 过载,哪个线程导致 CPU 过载,哪段代码导致 CPU 过载?

阅读全文 »

蓄水池抽样算法(Reservoir Sampling)

发表于 2018-11-02 | 更新于 2019-02-19 | 评论数: | 阅读次数:
本文字数: 2.8k | 阅读时长 ≈ 3 分钟

蓄水池抽样算法(Reservoir Sampling)

许多年以后,当听说蓄水池抽样算法时,将会想起,那个小学数学老师带他做 “小明对水池边加水边放水,求何时能加满水” 应用题的下午。

阅读全文 »

单例模式–双重检验锁真的线程安全吗

发表于 2018-11-02 | 更新于 2019-04-03 | 评论数: | 阅读次数:
本文字数: 2.9k | 阅读时长 ≈ 3 分钟

单例模式–双重检验锁真的线程安全吗

单例模式是我们最熟悉不过的一种设计模式,用来保证内存中只有一个对象的实例。虽然容易,但里面的坑也有很多,比如双重检验锁模式 (double checked locking pattern) 真的是线程安全的吗?

阅读全文 »
123

woo

愿你我能摆脱冷气,只是向上走,不必听自暴自弃者流的话。

28 日志
18 标签
GitHub E-Mail
Links
  • Google
  • Github
0%
© 2020 woo | 78k | 1:11
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Gemini v7.0.0