百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

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」领导总是能识破程...