Java编程中最容易忽略的10个常见问题分别有哪些

技术Java编程中最容易忽略的10个常见问题分别有哪些本篇文章给大家分享的是有关Java编程中最容易忽略的10个常见问题分别有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟

本文是关于Java编程中最容易被忽视的10个常见问题。边肖觉得很实用,所以想分享给大家学习。希望大家看完这篇文章能有所收获。话不多说,让我们和边肖一起看看。

在Java编码中,我们容易犯一些错误,忽略一些问题。因此,作者总结了日常编码中遇到的一些经典情况,供大家共同探讨。

Java编程中最容易忽略的10个常见问题分别有哪些

1. 纠结的同名

现象

许多类具有相同的名称(例如,它们在异常、常数、日志等中很常见。),这导致导入时有时会隐藏错误。因为同名的类往往功能相似,IDE不会提示警告。

解决

写完代码后,扫描导入部分,看看是否有不熟悉的部分。替换为正确导入后,请注意注释是否相应修改。

启示

命名要尽可能避免重名,尤其是避免与JDK的类重名,否则很容易导入不正确,而且重名的类很多,搜索的时候要花更多的时间去识别。

2. 想当然的API

现象

有时调用API时,会理所当然地直接、自信地按名称调用,导致一些令人惊讶的错误:

例flag是真的吗?

布尔标志=boolean . getboolean(' true ');

可能永远都是假的。

例:这是去年的今天吗(今年是2012年,不考虑闰年)?结果是2012年:

Calendar calendar=公历calendar . GetInstance();

日历。滚动(日历。年_月_日,-365);

以下是去年的情况:

日历。添加(日历。年_月_日,-365);

解决办法

问自己几个问题。这个方法我熟悉吗?有没有类似的API?有什么区别?就示例1而言,差异如下:

布尔.值Of(b) VS布尔.解析布尔(b) VS布尔.获取布尔(b);

启示

给出一个更详细的名字,做出更清晰的评论。不要在没有了解和测试的情况下,就把一些API当成理所当然。如果时间有限,可以使用自己最熟悉的API。

3. 有时候溢出并不难

现象

有时溢出并不难,尽管它并不经常重复:

例1:

长x=整数。MAX _ VALUE 1;

system . out . println(x);

x是什么?原来是-2147483648,加1后还是长的范围。类似的经常出现在时间计算中:

1次;次数2次;数字3hellip

例2:

在参数校验检查是否为正时,为了避免重载,参数号被选中,所以下面代码的结果小于0,这也是溢出造成的:

数字I=长。MAX _ VALUE

system . out . println(I . int value)(0);

解决

让* * *操作数长一些,比如加l或者l(不建议用小写字母l,因为和数字1太像了);

如果不确定,就用重载,也就是用doubleValue(),当参数是BigDecimal的时候,解决不了问题。

启示

对数字的使用保持敏感:当涉及数字计算时,应考虑溢出效应;说到除法,要考虑被除数为0;我真的忍不住了。我可以考虑大十进制等等。

4.日记在哪里?

现象

有时候觉得日志已经打好了,为什么找不到?

示例1:没有堆栈跟踪!

}捕获(例外情况){ 0

log . error(ex);

}

例2:找不到日志!

} catch(configuration exception e){ 0

e . printstacktrace();

}

解决

ol class=" list-paddingleft-2">

  • 替换成log.error(ex.getMessage(),ex);

  • 换成普通的log4j吧,而不是System.out。

  • 启示

    1. API定义应该避免让人犯错,如果多加个重载的log.error(Exception)自然没有错误发生

    2. 在产品代码中,使用的一些方法要考虑是否有效,使用e.printStackTrace()要想下终端(Console)在哪。

    5. 遗忘的Volatile

    现象

    在DCL模式中,总是忘记加一个Volatile。

    private static CacheImpl instance;  //lose volatile
    public static CacheImpl getInstance() {
        if (instance == null) {
            synchronized (CacheImpl.class) {
                if (instance == null) {
                    instance = new CacheImpl ();
                }
            }
        }
        return instance;
    }

    解决

    毋庸置疑,加上一个吧,synchronized 锁的是一块代码(整个方法或某个代码块),保证的是这”块“代码的可见性及原子性,但是instance == null***次判断时不再范围内的。所以可能读出的是过期的null。

    启示

    我们总是觉得某些低概率的事件很难发生,例如某个时间并发的可能性、某个异常抛出的可能性,所以不加控制,但是如果可以,还是按照前人的“***实践”来写代码吧。至少不用过多解释为啥另辟蹊径。

    6. 不要影响彼此

    现象

    在释放多个IO资源时,都会抛出IOException ,于是可能为了省事如此写:

    public static void inputToOutput(InputStream is, OutputStream os,
               boolean isClose) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(is, 1024);
        BufferedOutputStream bos = new BufferedOutputStream(os, 1024); 
        ….
        if (isClose) {
           bos.close();
           bis.close();
        }
    }

    假设bos关闭失败,bis还能关闭吗?当然不能!

    解决办法

    虽然抛出的是同一个异常,但是还是各自捕获各的为好。否则***个失败,后一个面就没有机会去释放资源了。

    启示

    代码/模块之间可能存在依赖,要充分识别对相互的依赖。

    7. 用断言取代参数校验

    现象

    如题所提,作为防御式编程常用的方式:断言,写在产品代码中做参数校验等。例如:

    private void send(List< Event> eventList)  {
        assert eventList != null;
    }

    解决

    换成正常的统一的参数校验方法。因为断言默认是关闭的,所以起不起作用完全在于配置,如果采用默认配置,经历了eventList != null结果还没有起到作用,徒劳无功。

    启示

    有的时候,代码起不起作用,不仅在于用例,还在于配置,例如断言是否启用、log级别等,要结合真实环境做有用编码。

    8. 用户认知负担有时候很重

    现象

    先来比较三组例子,看看那些看着更顺畅?

    示例一:

    public void caller(int a, String b, float c, String d) {
        methodOne(d, z, b);
        methodTwo(b, c, d);
    }
    public void methodOne(String d, float z, String b) 
    public void methodTwo(String b, float c, String d)

    示例二:

    public boolean remove(String key, long timeout) {
                 Future< Boolean> future = memcachedClient.delete(key);
    public boolean delete(String key, long timeout) {
                 Future< Boolean> future = memcachedClient.delete(key);

    示例三:

    public static String getDigest(String filePath, DigestAlgorithm algorithm)
    public static String getDigest(String filePath, DigestAlgorithm digestAlgorithm)

    解决

    1. 保持参数传递顺序;

    2. remove变成了delete,显得突兀了点, 统一表达更好;

    3. 保持表达,少缩写也会看起来流畅点。

    启示

    在编码过程中,不管是参数的顺序还是命名都尽量统一,这样用户的认知负担会很少,不要要用户容易犯错或迷惑。例如用枚举代替string从而不让用户迷惑到底传什么string, 诸如此类。

    9. 忽视日志记录时机、级别

    现象

    存在下面两则示例:

    示例一:该不该记录日志?

    catch (SocketException e)
    {
        LOG.error("server error", e);
        throw new ConnectionException(e.getMessage(), e);
    }

    示例二:记什么级别日志?

    在用户登录系统中,每次失败登录:

    LOG.warn("Failed to login by "+username+");

    解决

    1. 移除日志记录:在遇到需要re-throw的异常时,如果每个人都按照先记录后throw的方式去处理,那么对一个错误会记录太多的日志,所以不 推荐如此做;但是如果re-throw出去的exception没有带完整的trace( 即cause),那么***还是记录下。

    2. 如果恶意登录,那系统内部会出现太多WARN,从而让管理员误以为是代码错误。可以反馈用户以错误,但是不要记录用户错误的行为,除非想达到控制的目的。

    启示

    日志改不改记?记成什么级别?如何记?这些都是问题,一定要根据具体情况,需要考虑:

    1. 是用户行为错误还是代码错误?

    2. 记录下来的日志,能否能给别人在不造成过多的干扰前提下提供有用的信息以快速定位问题。

    10. 忘设初始容量

    现象

    在JAVA中,我们常用Collection中的Map做Cache,但是我们经常会遗忘设置初始容量。

    cache = new LRULinkedHashMap< K, V>(maxCapacity);

    解决

    初始容量的影响有多大?拿LinkedHashMap来说,初始容量如果不设置默认是16,超过16&times;LOAD_FACTOR,会resize(2  * table.length),扩大2倍:采用 Entry[] newTable = new Entry[newCapacity];  transfer(newTable),即整个数组Copy,  那么对于一个需要做大容量CACHE来说,从16变成一个很大的数量,需要做多少次数组复制可想而知。如果初始容量就设置很大,自然会减少resize,  不过可能会担心,初始容量设置很大时,没有Cache内容仍然会占用过大体积。其实可以参考以下表格简单计算下, 初始时还没有cache内容,  每个对象仅仅是4字节引用而已。

    • memory for reference fields (4 bytes each);

    • memory for primitive fields

    Java type

    Bytes required

    boolean

    1

    byte

    char

    2

    short

    int

    4

    float

    long

    8

    double

    启示

    不仅是map, 还有stringBuffer等,都有容量resize的过程,如果数据量很大,就不能忽视初始容量可以考虑设置下,否则不仅有频繁的 resize还容易浪费容量。

    在Java编程中,除了上面枚举的一些容易忽视的问题,日常实践中还存在很多。

    以上就是Java编程中最容易忽略的10个常见问题分别有哪些,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

    内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/56690.html

    (0)

    相关推荐

    • 别看今天闹得欢,为什么现在肺癌越来越多

      技术别看今天闹得欢,为什么现在肺癌越来越多一说肺癌别看今天闹得欢,立马联想到吸烟。的确,如果一个人烟瘾大,一枝接着一枝的吸,那么会是一口接着一口吸的是烟气,而不是清新的空气。试想 ,会对肺部该有多大的损害。在吸烟如命人的

      生活 2021年10月25日
    • 如何解析PHP的Invalid binding type问题

      技术如何解析PHP的Invalid binding type问题如何解析PHP的Invalid binding type问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能

      攻略 2021年10月23日
    • 如何分析Python自动化运维开发中的变量

      技术如何分析Python自动化运维开发中的变量本篇文章给大家分享的是有关如何分析Python自动化运维开发中的变量,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看

      攻略 2021年12月4日
    • 外部css样式表的作用是什么

      技术外部css样式表的作用是什么本篇内容主要讲解“外部css样式表的作用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“外部css样式表的作用是什么”吧!

      攻略 2021年11月3日
    • 会意字大全,象形、指事、会意、形声字各二十个

      技术会意字大全,象形、指事、会意、形声字各二十个象形字:雨会意字大全、元、木、眉、左、右、门、龟、车、月、龟、马、鱼、日、门、木、山、手、羊、草、鸟、虫、川、耳、口、人、田、水、火 指事字:上、一、二、下、丨、丩、爻、元

      2021年10月21日
    • 租用台湾云服务器有什么好处

      技术租用台湾云服务器有什么好处台湾云服务器采用虚拟化技术将高性能服务器集群分为多个虚拟服务器。这些虚拟服务器是私有的,因为用户不必与同一物理服务器上的其他方共享磁盘空间、CPU、内存。台湾云服务器租用对您网站的好处 租用

      礼包 2021年12月8日