关于写代码的几个看法

最近在新公司负责bug的修复,发现很多的代码逻辑理解起来有些困难。现在将其中观察到的现象列出来,谈谈自己的看法。

1.类过大

对于代码来说,我们在编写的时候最好做到SRP(Single Responsibility Principle)。但是实际的项目由于经过了不同的开发人员,以及工期比较紧张的原因,所以这一原则被遵守的不是很好。经常看到一个函数100多行,可能我遇到的还算好的了,这个问题不是最大的。

修改建议:一个函数最好控制在30--50行左右

2.同样的一种情况,用多个变量表示

比如说对于视频格式,HLS(m3u8)有时候叫hls,有时候叫m3u8,这个问题还好,然后一个bool的变量代表hls(hlsType_),一个代表m3u8(m3u8Type_).判断的时候有时候用hlsType_,有时候用m3u8Type_,导致判断变量不明确。一个地方忘记修改,就非常容易出现bug。

修改建议:对于一个类型,只用一种标志,判断方式最好由函数导出而不是直接判断变量类型。

3.在函数的参数中,引入bool类型的控制变量

在函数中引入bool变量被成为逻辑耦合,这对于代码的理解是非常不好的。
具体的分析 https://coolshell.cn/articles/5444.html 。记得代码中有个函数是这样的

void Func(Client& client,bool dns,bool complete).

表示智商不好的我,问了好多次领导终弄明白了,就赶快加上了注释。
能猜出来dns和complete的含义和关系的同学,我向你们表示敬意。
修改建议:不在函数中写入bool变量。

4.数据传输和业务逻辑未分离

对于网络编程来说,主要涉及到两个部分。1.socket IO和2.协议解析 其实这两个部分是正交的,举个例子说明一下。

比如 “乾隆” 让 “和大人” 到宫里商量事情,用的是两个人只懂的暗号,这就是协议。
这个消息怎么让“和大人”知道就是socket IO。
比如协议可以选择 1.满文 2.汉文 或者 3.诗词中的一些话。
传输方式可以选择 1.口谕 2.圣旨 3.信鸽 。
可以形成一个组合型的矩阵。

协议满文汉文
口谕满文口谕汉文口谕
信鸽信鸽带满文纸条信鸽带汉文纸条

这样的设计在扩充协议或者传输方式的时候都非常的容易,而且每个部分各司其职,非常容易理解。

修改建议:将协议解析和数据传输分开,容易理解。

5.减少类的成员变量,相关变量合并和注释

在很多的代码规范中,会提到尽量少用或者不用全局变量,对于类来说,就是尽量减少类的成员变量,能用局部变量或者函数参数的方式表示的,尽量不要选择用成员变量来表示。在对于需要一些计算结果的情况下,要做到不要边接受数据,边计算中间结果。因为如果要对最后的结果进行修正的话,中间结果也需要修正,会增加程序的修改位置和难度。

修改建议:只保留数据的原始结果,在最后的步骤中计算最后的结果。

类的成员变量==类函数的全局变量

转载于:https://www.cnblogs.com/Dennis-mi/p/8410655.html

<think>好的,我现在需要解决的问题是:当在Java中执行`String s = "a" + "b";`时,会创建多少个对象?这个问题看起来是关于字符串拼接Java字符串常量池的知识。我需要仔细分析这个表达式,并回忆相关的Java知识。 首先,用户之前询问的是TCP粘包拆包的问题,现在突然转向Java字符串的问题,这可能是一个测试或者对技术广度的考察。我需要确保回答准确,同时易于理解。 首先,分解这个表达式:`String s = "a" + "b";`。这里有两个字符串字面量"a""b",它们被加号连接,然后赋值给变量s。关键点在于字符串拼接在Java中是如何处理的,尤其是在编译时运行时的不同行为。 我记得Java中的字符串常量池(String Pool)的概念。字符串字面量在编译时会被放入常量池中,所以当使用字面量时,JVM会检查常量池是否存在该字符串,存在则直接引用,不存在则创建新的对象。例如,"a""b"作为字面量,在类加载的时候就会被放入常量池,每个对应一个String对象。 接下来是拼接操作。这里使用的是两个常量字符串的拼接。根据Java编译器优化,如果拼接的双方都是常量表达式(即编译时可以确定值的),那么编译器会进行优化,直接将它们拼接成一个常量,即"ab"。这时候,在编译后的字节码中,`"a" + "b"`会被替换成"ab",而不会在运行时进行拼接操作。因此,在常量池中会存在"a"、"b""ab"这三个字符串吗? 需要确认的是,在编译阶段,编译器是否会将"a"+"b"合并为"ab",从而在类文件中直接生成"ab"这个常量。如果是这样的话,那么在运行的时候,只会从常量池中取出"ab"的引用,而不会创建新的String对象。因此,整个过程可能只会涉及三个字符串对象:"a"、"b"、"ab",但这些都是在编译时就已经存在于常量池中的,因此执行该语句时不会创建新的对象,而是直接引用已有的对象。 不过,这里需要注意,如果在代码中之前没有出现过这些字符串,那么当类加载的时候,这些字符串会被创建并放入常量池中。所以,假设在程序的其他地方没有使用过这些字符串,那么当类加载时,会创建"a"、"b""ab"三个字符串对象,存放在常量池中。执行该语句时,s变量直接指向常量池中的"ab",而不会在堆中创建新的String对象。 但有时候可能会有误解,认为使用+操作符会在运行时生成新的对象,特别是当操作数不是常量的时候。例如,如果两个变量相加,那么会在运行时使用StringBuilder来进行拼接,生成新的String对象。但在这个问题中,操作数是字面量,所以属于常量表达式,编译器会优化。 那么回到问题本身,当执行`String s = "a" + "b";`时,创建了几个对象?这里的“创建”指的是在运行时创建的对象数量,还是在类加载时创建的数量? 可能用户想问的是执行该行代码时,会创建多少个新的对象。如果是这样的话,因为"a""b"已经在常量池中存在,而"ab"在编译时已经被优化成一个常量,所以在执行该行代码时,并不会创建任何新的对象,而是直接引用常量池中的"ab"。所以此时答案是0个新对象被创建,因为这三个字符串已经在常量池中存在了。 不过,如果考虑类加载阶段,当类被加载时,会将这些字符串字面量(包括"a"、"b"以及由编译器优化生成的"ab")放入常量池中。此时,这三个字符串对象是在类加载的时候被创建的。但用户的问题可能关注的是执行该语句时创建了多少对象,而不是整个类的生命周期中。 所以需要明确问题的时间点。例如,假设在类加载时,常量池中已经存在这三个字符串,那么执行该语句时不会创建新对象。如果程序中没有其他代码使用到这些字符串,那么当加载这个类时,这三个字符串会被创建到常量池中,所以在整个程序运行期间,这三个对象会被创建,而该行代码本身并不创建新对象。 但是,可能有些特殊情况需要考虑,比如是否真的存在编译器优化将"a"+"b"合并为"ab"。这时候,需要通过实际编译后的代码来验证。例如,可以使用javap命令查看字节码。 假设编一个简单的类: public class Test { public static void main(String[] args) { String s = "a" + "b"; } } 然后编译,并用javap -c Test查看main方法的字节码: public static void main(java.lang.String[]); Code: 0: ldc #2 // String ab 2: astore_1 3: return 可以看到,在编译后,字符串拼接已经被优化成"ab",直接使用ldc(load constant)指令将常量池中的"ab"加载到栈中,然后存储到变量s中。这说明编译器确实将"a"+"b"优化为"ab",因此在字节码中并没有出现两个字符串的拼接操作,而是直接引用了"ab"。 因此,在编译后的代码中,字符串"ab"作为常量存在于常量池中,当类被加载时,"a"、"b""ab"这三个字符串都会被创建并放入常量池中。所以,在类加载阶段,这三个字符串对象被创建。而执行该语句时,只是将已经存在的"ab"的引用赋值给变量s,不会创建新对象。 因此,问题中的代码行执行时,并不会创建新的对象,而只是引用已有的常量池中的对象。因此,答案应该是:创建了0个对象,因为所有的字符串已经在常量池中存在了。但可能用户的问题是否考虑类加载时的创建? 如果用户的问题是“这行代码执行时会创建多少个对象”,那么答案是0个。如果是整个程序运行期间,因为该代码的存在,导致创建了多少个字符串对象,那么可能答案是三个,即"a"、"b"、"ab",但这些是在类加载时创建的,而不是在执行该行代码时创建的。 但一般情况下,当面试或类似的问题中,问的是执行该行代码时创建了多少个对象,这时候的答案通常是0或者1,具体要看情况。但根据上面的分析,因为编译器优化,所以此时在代码执行时,并没有创建新对象,而是直接引用已有的"ab"。 不过,有一种可能的混淆点是,当字符串常量池中还没有"ab"的时候,执行该行代码是否会创建它。但根据Java规范,字符串常量池中的字符串是在类加载的时候被创建的,所以当类被加载时,所有的字面量编译时常量表达式的结果都会被创建并放入池中。因此,在执行该行代码之前,"ab"已经存在于池中,所以执行时不需要创建。 总结: - 编译阶段,编译器将"a"+"b"优化为"ab",因此代码中的拼接被替换为常量"ab"。 - 类加载时,会将"a"、"b"、"ab"三个字符串对象创建并放入常量池。 - 执行该行代码时,只是将常量池中的"ab"引用赋值给变量s,不创建新对象。 因此,执行该行代码时,并不会创建任何新的对象。所以答案应该是创建了0个对象。但需要注意前提是这三个字符串在之前没有被加载过,如果是第一次加载,那么在类加载时创建这三个对象,但问题中的代码行执行时并不创建。 不过,可能有些资料或面试题中的答案会认为,当字符串拼接时,如果结果是编译时常量,则不会在运行时创建新对象,而只在常量池中存在。因此,这种情况下,该行代码执行时不会创建新对象。所以答案是0个对象被创建,或者如果考虑类加载阶段,则创建了三个对象,但执行时0个。 因此,问题的答案可能需要根据上下文来判断,但通常在这种情况下,答案会是1个对象,即"ab"字符串,或者认为在编译时已经合并,因此执行时不创建新对象。不过根据之前的分析,正确的答案应该是执行时没有创建新对象,而"ab"是在类加载时创建的。 可能用户的问题期望的答案是,在字符串常量池中,"a""b"会被创建,而"ab"也会被创建,所以总共三个对象。但是根据编译器的优化,"a"+"b"被合并为"ab",所以可能实际只有"ab"被创建?或者原问题中的两个字符串"a""b"是否会被放入常量池? 这里需要明确,每个字符串字面量都会在类加载时被放入常量池。因此,即使代码的是"a"+"b",但原代码中的字面量"a""b"还是会被放入常量池中,而编译器优化后的结果"ab"也会被当作一个字面量,放入常量池。因此,这三个字符串都会被创建,所以总共有三个对象。但是,这可能发生在类加载阶段,而不是执行该行代码的时候。 因此,如果用户的问题中的“创建几个对象”指的是执行该行代码时创建的对象数目,那么答案是0,因为这三个对象已经在类加载时创建了。如果问题指的是整个过程中(包括类加载)创建了多少个字符串对象,那么是三个:"a"、"b"、"ab"。 但通常,在Java面试题中,这样的问题可能期望的答案是,在运行该行代码时,创建了一个对象,即"ab"字符串。这可能是因为误解,或者不同的编译器行为。或者,可能认为当使用+操作符时,会生成新的对象。但根据优化,实际上并不会。 例如,如果代码中是`String s = new String("a") + new String("b");`,那么情况就不同,会在堆中创建多个对象。但原问题中的是字面量相加,所以属于编译时常量。 因此,正确的结论是,在类加载时,常量池中会创建"a"、"b""ab"这三个字符串对象,因此在执行该行代码时,没有新对象被创建。所以,答案是0个对象在该行代码执行时被创建,而三个对象在类加载时被创建。但用户的问题可能更关注的是该行代码执行时的对象创建数目,所以答案是0。 不过,也有可能存在不同的看法。比如,有人认为,即使"a""b"已经被放入常量池,但它们的拼接可能在运行时生成新的对象。但根据编译器的优化,这种情况不会发生,而是直接使用已经存在的"ab"。 为了验证这一点,可以编测试代码: public class Test { public static void main(String[] args) { String a = "a"; String b = "b"; String s1 = "a" + "b"; String s2 = "ab"; System.out.println(s1 == s2); // 输出true } } 运行后,输出为true,说明s1s2都指向同一个常量池中的对象,证明"a"+"b"被编译器优化为"ab",因此不会在运行时创建新对象。 因此,回到原问题,`String s = "a" + "b";` 在编译时已经被替换为`String s = "ab";`,因此该行代码执行时,s引用的是常量池中的"ab",而不会创建新的对象。同时,在类加载时,已经创建了"a"、"b""ab"这三个字符串对象。 所以,问题的答案取决于用户想问的是哪个阶段。如果是在类加载阶段,则三个对象被创建;如果是在执行该行代码时,则没有新对象创建。通常,在面试中,这个问题的答案可能期望的是执行时创建了一个对象,但根据实际分析,正确的答案应该是0,因为优化后的代码直接引用现有的对象。 不过,另一种可能性是,当代码中使用的是两个不同的字符串字面量,而编译器将它们合并为一个,那么是否在常量池中这三个对象都存在?例如,假设原来的代码中只有"a"+"b",那么"a""b"是否会被放入常量池? 是的。例如,在类中如果有任何地方使用了字符串字面量"a"或"b",那么它们会被放入常量池。即使拼接后的结果是"ab",编译器优化后,但原代码中的字面量"a""b"仍然会被视为常量,因此会被放入常量池中。因此,在类加载时,这三个对象都会被创建。 总结: - 类加载阶段,"a"、"b""ab"被创建到字符串常量池中。 - 执行该行代码时,没有新对象被创建,s指向已经存在的"ab"。 因此,该行代码执行时创建的对象数目是0。但整个程序运行期间,这三个字符串对象被创建。所以,回答这个问题时需要明确上下文。 可能用户的问题的正确答案是,在执行该行代码时,没有创建新的对象,但整个程序中,这三个字符串对象被创建。或者,如果问题指的是在代码行执行时,会创建多少对象,那么答案是0。然而,有些资料可能给出不同的答案,例如认为会创建一个对象,即"ab",但根据Java的优化机制,这应该是不正确的。 因此,最终答案应该是:在执行该行代码时,不会创建任何新的字符串对象,而s变量指向字符串常量池中已存在的"ab"。因此,创建的对象数目为0个。但需要注意,这行代码会导致类加载时(如果尚未加载)创建三个字符串对象:"a"、"b"、"ab"。</think>在Java中,执行 `String s = "a" + "b";` 时,**不会在运行时创建新的对象**。这是因为: 1. **编译期优化**: Java编译器会将**常量表达式**(如字面量拼接)优化为最终结果。代码中的 `"a" + "b"` 会被直接编译为 `"ab"`,等价于 `String s = "ab";`。 2. **字符串常量池机制**: - 类加载时,字面量 `"a"`、`"b"` `"ab"` 会被存入**字符串常量池**(每个字面量对应一个对象)。 - 执行该代码时,变量 `s` 直接引用常量池中已有的 `"ab"`,**无需创建新对象**。 --- ### **关键结论** - **类加载阶段**:常量池中创建 `"a"`、`"b"`、`"ab"` 三个对象(仅首次加载时)。 - **代码执行阶段**:**0个新对象被创建**,`s` 直接指向常量池的 `"ab"`。 --- ### **验证示例** ```java public class Test { public static void main(String[] args) { String s1 = "a" + "b"; String s2 = "ab"; System.out.println(s1 == s2); // 输出 true(指向同一对象) } } ``` 结果输出 `true`,证明 `s1` `s2` 引用的是常量池中的同一对象。 --- ### **对比:非字面量拼接** 若拼接操作含变量(非常量表达式),则会在**堆内存**中创建新对象: ```java String a = "a"; String b = "b"; String s3 = a + b; // 运行时通过 StringBuilder 生成新对象 System.out.println(s3 == "ab"); // 输出 false ``` 此时 `s3` 是堆中的新对象,与常量池的 `"ab"` 不同。 --- ### **总结** - **常量拼接**(如 `"a"+"b"`):编译优化 + 常量池引用 → **无新对象**。 - **变量拼接**(如 `a + b`):运行时生成新对象 → **创建新对象**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值