Java编程的那些屎山代码分析之二(java编程神器)
yund56 2025-07-28 23:32 4 浏览
以下是个人总结的一些代码习惯问题和优化,单独一个也许不起眼,但堆积起来,就让一个项目代码变成一座屎山。
1.滥用`public`修饰符
o 重要性:滥用`public`修饰符可能导致类的成员变量或方法被不恰当地公开,增加不必要的暴露和模块间的耦合。o 避免方法:默认使用`private`或`package-private`访问控制符,仅当需要外部访问时提供公共的 getter 和 setter 方法。
举个正例:
public class MyClass {
private int value;
public int getValue() { return value; }
public void setValue(int value) { this.value = value; }
}
举个反例:
public class MyClass {
public int value;
}
2.字符串拼接使用`+`
o 重要性:在循环中使用`+`进行字符串拼接可能导致性能问题,因为每次拼接都会创建新的字符串对象。o 避免方法:使用`StringBuilder`或`String.format`来提高性能。
举个正例:
StringBuilder result = new StringBuilder();
for (int i = 0; i < 1000; i++) {
result.append(i);
}
举个反例:
String result = "";
for (int i = 0; i < 1000; i++) {
result += i;
}
3.在多线程中共享可变状态
o 重要性:在多线程环境中共享可变状态可能导致线程安全问题。o 避免方法:使用不可变对象或通过同步机制来管理状态。
举个正例:
import java.util.concurrent.atomic.AtomicInteger;
class Counter {
private AtomicInteger count = new AtomicInteger(0);
public int increment() {
return count.incrementAndGet();
}
}
举个反例:
class Counter {
int count = 0;
}
4.在集合中使用原始类型
o 重要性:使用原始类型可能导致`ClassCastException`。o 避免方法:使用泛型来避免类型转换问题。
举个正例:
List<String> list = new ArrayList<>();
list.add("test");
String str = list.get(0);
举个反例:
List list = new ArrayList();
list.add("test");
String str = (String) list.get(0);
5.使用硬编码字符串
o 重要性:硬编码字符串使得代码难以维护和国际化。o 避免方法:使用常量或资源文件来管理字符串。
举个正例:
public static final String ADMIN = "admin";
if (userType.equals(ADMIN)) {
// do something
}
举个反例:
if (userType.equals("admin")) {
// do something
}
6.不使用日志框架
o 重要性:不使用日志框架可能导致调试和问题跟踪困难。o 避免方法:使用如 SLF4J 或 Log4j 等日志框架。
举个正例:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.error("错误信息");
举个反例:
System.out.println("错误信息");
7.错误使用浮点数进行比较题
o 错误使用浮点数进行比较o 重要性:直接比较浮点数可能导致逻辑错误,因为浮点数的精度问题。o 避免方法:使用误差范围进行比较。
举个正例:
if (Math.abs(0.1 + 0.2 - 0.3) < 1e-9) {
System.out.println("相等");
}
举个反例:
if (0.1 + 0.2 == 0.3) {
System.out.println("相等");
}
8.循环中创建对象
o 重要性:在循环中创建对象可能导致性能问题和内存浪费。o 避免方法:将对象初始化移到循环外部。
举个正例:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append(i);
}
举个反例:
for (int i = 0; i < 100; i++) {
StringBuilder sb = new StringBuilder();
}
9.过度依赖静态变量
o 重要性:过度依赖静态变量可能导致线程不安全。o 避免方法:限制静态变量的使用,优先使用实例变量或线程本地变量。
举个正例:
private int counter = 0;
举个反例:
public static int counter = 0;
10.不规范的命名
o 重要性:不规范的命名降低代码可读性。o 避免方法:遵循命名规范,如 CamelCase。
举个正例:
public void getData() { }
举个反例:
public void GETdata() { }
11.滥用反射
o 重要性:滥用反射可能导致性能差且不安全。o 避免方法:仅在必要时使用反射。
举个正例:
List<String> list = new ArrayList<>();
举个反例:
Class<?> clazz = Class.forName("java.util.ArrayList");
Object obj = clazz.newInstance();
12.在集合中存放过多元素
o 重要性:存放过多元素可能导致内存溢出。o 避免方法:设置合理的容量或限制集合大小。
举个正例:
List<Integer> list = new ArrayList<>(1000); // 添加有限数量的元素
举个反例:
List<Integer> list = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
list.add(i);
}
13.使用双重检查锁定时未声明`volatile`
o 重要性:未声明`volatile`可能导致线程安全问题。o 避免方法:使用`volatile`或枚举单例模式。
举个正例:
class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
举个反例:
class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
14.直接暴露内部数据结构
o 重要性:直接暴露内部数据结构容易破坏封装性。o 避免方法:提供不可变集合或深拷贝。
举个正例:
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
举个反例:
public List<String> getItems() {
return items;
}
15. 滥用`instanceof`
o 重要性:滥用`instanceof`可能导致代码难以维护。o 避免方法:使用多态。
举个正例:
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing Circle");
}
}
Shape shape = new Circle();
shape.draw();
举个反例:
if (obj instanceof Circle) {
Circle circle = (Circle) obj;
circle.draw();
}
16.在`HashMap`中使用可变键
o 重要性:使用可变键可能导致数据丢失或行为异常。o 避免方法:使用不可变对象作为键。
举个正例:
Map<String, String> map = new HashMap<>();
String key = "constantKey";
map.put(key, "value");
System.out.println(map.get(key)); // 返回 value
举个反例:
Map<List<String>, String> map = new HashMap<>();
List<String> key = new ArrayList<>();
map.put(key, "value");
key.add("newKey");
System.out.println(map.get(key)); // 可能返回 null
17.直接调用线程的`run()`方法
o 重要性:直接调用`run()`方法可能导致逻辑错误,原因详见备注1。
o 避免方法:使用`start()`方法启动线程。
举个正例:
Thread thread = new Thread(() -> System.out.println("Running"));
thread.start();
举个反例:
Thread thread = new Thread(() -> System.out.println("Running"));
thread.run();
18.滥用`System.exit()`
o 重要性:滥用`System.exit()`可能导致资源未释放。o 避免方法:避免使用`System.exit()`,正常流程中结束程序。
举个正例:
if (error) {
throw new RuntimeException("程序出现错误");
}
举个反例:
if (error) {
System.exit(1);
}
19.在循环中频繁调用`get`方法
o 重要性:频繁调用`get`方法可能导致性能问题。o 避免方法:使用局部变量存储返回值。
举个正例:
List<Integer> list = new ArrayList<>();
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.get(i));
}
举个反例:
List<Integer> list = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
20.在同步代码块中使用`String`锁
o 重要性:使用`String`锁可能引发死锁。o 避免方法:使用私有的锁对象。
举个正例:
代码private final Object lock = new Object();
synchronized (lock) {
System.out.println("Locked");
}
举个反例:
synchronized ("lock") {
System.out.println("Locked");
}
21.使用过时的类或方法
o 重要性:使用过时的类或方法可能存在安全问题或性能低下。o 避免方法:使用现代替代方案。
举个正例:
LocalDate date = LocalDate.of(202
举个反例:
Date date = new Date(2022, 1, 1);
22.未对集合进行空检查
o 重要性:未进行空检查可能引发`NullPointerException`。o 避免方法:使用`Objects.isNull`或`Objects.nonNull`检查。
举个正例:
import java.util.Objects;
List<String> list = null;
if (Objects.nonNull(list)) {
System.out.println(list.size());
}
//或者使用Java 8 的 Optional 类来避免空检查:
import java.util.List;
import java.util.Optional;
List<String> list = null;
Optional.ofNullable(list).ifPresent(l -> System.out.println(l.size()));
举个反例:
List<String> list = null;
System.out.println(list.size());
23.递归调用未限制深度
o 重要性:未限制深度可能导致栈溢出。o 避免方法:添加递归终止条件或改为迭代。
举个正例:
void recursive(int depth) {
if (depth == 0) return;
recursive(depth - 1);
}
举个反例:
void recursive() {
recursive();
}
备注:
一,线程使用run方法执行的问题
1. 生命周期管理:
o 当你创建一个线程并调用其 run() 方法时,这个线程并没有被当作一个线程来执行,而是作为一个普通的对象方法调用。这意味着线程的生命周期并没有被正确管理,它没有被放置在线程调度器的控制之下。
o 线程的启动和执行应该由 Java 虚拟机(JVM)的线程调度器来管理。通过调用 start() 方法而不是 run() 方法,线程会被正确地放入 JVM 的线程调度队列中,按照线程的优先级和调度策略被执行。
2. 并发执行:
o start() 方法会创建一个新的线程,并在这个新线程中调用 run() 方法,从而实现并发执行。这意味着主线程和新线程可以同时运行,这是多线程编程的核心优势之一。
o 如果直接调用 run() 方法,就不会创建新的线程, run() 方法的执行会阻塞当前线程,直到 run() 方法执行完成,这失去了并发执行的意义。
3. 线程局部变量:
o 在多线程环境中,线程局部变量(ThreadLocal)是每个线程独有的,它们通过 start() 方法启动的线程来隔离和管理。
o 如果直接调用 run() 方法,线程局部变量可能不会按预期工作,因为实际上并没有创建新线程,因此无法保证变量的线程安全性和隔离性。
4. 异常处理:
o 当线程通过 start() 方法启动时,在其 run() 方法中抛出的任何未捕获异常都会作为线程的运行时异常被捕获,并且可以通过 getStackTrace() 方法从外部获取堆栈跟踪,这有助于调试。
o 如果直接调用 run() 方法,任何在 run() 方法中抛出的异常都会导致当前线程(可能是主线程)崩溃,这可能导致程序的其他部分无法正常执行,并且可能使得异常处理更加困难。
如果不注意以上相关规范,写出这样一座屎山代码,对后续接手的人来说,是多大的伤害啊!
相关推荐
- 在这款15年老端游的手机版中,正在上演着“萌新拯救计划”
-
以往我们判断一款刚公测的新手游到底火不火,不是瞅苹果的免费榜畅销榜,就是看各家数据网站的预估流水。不过如今这个法子放在《剑网3无界》身上似乎就不那么适用了。作为一款与原端游完全数据互通的手游,点卡制收...
- 708090后集体回忆!88款经典街机游戏,你通关过几部?
-
街机厅的霓虹灯在夜色中闪烁,投币口“叮当”的声响此起彼伏,摇杆与按键的碰撞声混合着玩家的欢呼与叹息,构成了那个年代独有的电子交响乐。对于70后、80后、90后来说,街机不仅是游戏,更是一段无法复制的...
- 爷青回!这10款童年小游戏,玩过5个以上的都当爸妈了吧?
-
当手机游戏被3A画质与开放世界统治的今天,那些藏在像素点阵里的童年记忆,才是真正刻进DNA的快乐密码!我们翻遍全网玩家回忆录,结合抖音、Steam等平台数据,为你揭开这代人的集体记忆封印一、经典益智三...
- 怀旧时刻:PS2十大经典动作游戏盘点,老玩家不可错过的青春回忆
-
说起PS2,那可是游戏史上最火的主机之一,上面好游戏多得数不清,给咱们带来过不少欢乐时光。今天,小核桃就带大家回忆一下PS2上那些超经典的动作游戏,一起重温那些热血沸腾的日子吧!当年在电玩店看到《战神...
- 又是一年仲夏,三十年前的暑假,你还记得在玩什么游戏吗?
-
今年山东的夏天似乎比往年都热,夜晚繁星点点,本该轻柔的晚风却没有丝毫凉意,伴随着远处草丛里此起彼伏的虫鸣声,听的让人心里愈加烦躁,翻来覆去睡不着的笔者,无聊且乏困地坐在院子里的老槐树下,思绪却不由自主...
- 十六年前的首款安卓1.0手机,内置物理全键盘,如今二手45元
-
周末聊点轻松的话题,说起智能手机系统之争,安卓和iOS绝对是两大“宿敌”。2007年苹果在乔布斯带领下发布了初代iPhone,也凭借iOS系统掀起了智能手机的新时代。短短一年后,谷歌联合HTC推出了...
- HTC巅峰时期的安卓手机,自带全键盘,居然很多人用过
-
上次写三部最经典的侧滑盖全键盘手机,居然很多人报出了DesireZ的大名,这让我很吃惊。因为这部手机没有行货只有水货,你们咋都用过?那今天好好聊聊它。十多年前,HTC是安卓手机领域绝对的霸主,当年只...
- 十年前的 iPhone 6s 还在 “服役”:一部手机的 “超长待机” 启示录
-
当iPhone16系列已经开始预热,有人却还握着2015年发布的iPhone6s刷着微信、看视频——这部诞生已近十年的手机,至今仍在不少人的生活里扮演着重要角色。它的“超长寿命”...
- SFC黄金时代10款动作RPG神作,每一款都是回忆满满的经典游戏!
-
任天堂的16位主机SFC可是游戏史上的一个高峰,它用像素画面打造出无数经典作品,其中结合动作和冒险的ARPG特别受欢迎。最近几年复古风又火起来,大厂们忙着移植或重制老游戏,模拟器也让玩家轻松重温旧梦。...
- 揭秘十年前真正的游戏手机:索尼爱立信R800魔改系统超乎想象!
-
对于游戏手机的起源,众说纷纭,有人认为是黑鲨问世,有人说是红魔领路,还有人坚称自从iPhone问世起,游戏手机就已然存在。然而,如果从更宏观的角度审视,这些所谓的游戏手机,其本质上仍旧是多功能的智能手...
- 专属于八零,九零后的插卡游戏,你还记得吗
-
1.魂斗罗这是我玩过的第一款插卡游戏,永远记得上上下下左左右右,BABA开始,这个可以有三十条命的“魔法。”也是第一次体验双打游戏的那行配合的责任感使命感。2.忍者神龟四只神龟的名字都是意大利著名的画...
- Java编程的那些屎山代码分析之二(java编程神器)
-
以下是个人总结的一些代码习惯问题和优化,单独一个也许不起眼,但堆积起来,就让一个项目代码变成一座屎山。1.滥用`public`修饰符o重要性:滥用`public`修饰符可能导致类的成员变量或方法被不...
- 六种java的多线程设计模式详解和代码举例
-
java的多线程处理,有哪些模式可以使用呢,如何使用呢。本文列举了六种多线程设计模式供大家参考。1.生产者-消费者模式设计理念:生产者-消费者模式通过协调两个线程(生产者和消费者)来处理数据,生产者生...
- java的四种引用(java 中都有哪些引用类型)
-
java中的引用分为4种1.强引用引用存在就不会被GC*2.软引用heapmemory(堆内存)满了就会被GC掉*3.弱引用每次GC就会回收掉(应用有:ThreadLocal)*4....
- @程序员 2020了看不懂这些动图,你可能是个假的程序员
-
点击上方Java编程技术乐园,轻松关注!及时获取有趣有料的技术文章文章很有趣,开心一下,如果有收获,记得点赞和关注哦~「1」外包产品交付,给客户演示时「2」与领导斗智斗勇,躲猫猫「3」领导总是能识破程...
- 一周热门
- 最近发表
-
- 在这款15年老端游的手机版中,正在上演着“萌新拯救计划”
- 708090后集体回忆!88款经典街机游戏,你通关过几部?
- 爷青回!这10款童年小游戏,玩过5个以上的都当爸妈了吧?
- 怀旧时刻:PS2十大经典动作游戏盘点,老玩家不可错过的青春回忆
- 又是一年仲夏,三十年前的暑假,你还记得在玩什么游戏吗?
- 十六年前的首款安卓1.0手机,内置物理全键盘,如今二手45元
- HTC巅峰时期的安卓手机,自带全键盘,居然很多人用过
- 十年前的 iPhone 6s 还在 “服役”:一部手机的 “超长待机” 启示录
- SFC黄金时代10款动作RPG神作,每一款都是回忆满满的经典游戏!
- 揭秘十年前真正的游戏手机:索尼爱立信R800魔改系统超乎想象!
- 标签列表
-
- filter函数js (37)
- filter函数excel用不了 (73)
- 商城开发 (40)
- 影视网站免费源码最新版 (57)
- 影视资源api接口 (46)
- 网站留言板代码大全 (56)
- java版软件下载 (52)
- java教材电子课本下载 (48)
- 0基础编程从什么开始学 (50)
- java是用来干嘛的 (51)
- it入门应该学什么 (55)
- java线上课程 (55)
- 学java的软件叫什么软件 (38)
- 程序开发软件有哪些 (53)
- 软件培训 (59)
- 机器人编程代码大全 (50)
- 少儿编程教程免费 (45)
- 新代系统编程教学 (61)
- 共创世界编程网站 (38)
- 亲测源码 (36)
- 三角函数积分公式表 (35)
- 函数的表示方法 (34)
- 表格乘法的公式怎么设置 (34)
- sumif函数的例子 (34)
- 图片素材 (36)