- 博客(42)
- 资源 (1)
- 收藏
- 关注
原创 《Effective Java》第27条:消除非受检的警告
如果无法消除警告,同时可以证明引起警告的代码是类型安全的,(只有在这种情况下)才可以用一个 @SuppressWarnings(“unchecked”) 注解来禁止这条警告。但是如果忽略(而不是禁止)明知道是安全的非受检警告,那么当新出现一条真正有问题的警告时,你也不会注意到。尽量消除非受检警告,不要忽略他们,如果确实无法消除警告,并且能确定该警告不会引起运行时候的问题,可以在最小范围内使用@SuppressWarnings(“unchecked”) 注解,并且要把禁止该警告的原因写到注释上。
2025-12-24 14:04:56
269
原创 《Effective Java》第26条:请不要使用原生态类型
为什么是不合法的,原因有二,一是泛型的「类型擦除」机制 ,Java 的泛型是编译期特性,运行时会执行「类型擦除」—— 即参数化类型的泛型信息会被擦除,还原为原生态类型,也就是说,编译期的 List 和 List,在运行时都会被擦除为 List(原生态类型)。在日常的编程中,在不确定或者不在乎集合中的元素类型的情况下,你也许会使用原生态类型,例如书上P96页的例子,但这也不是一种好的方式使用原生态类型,此时通常会使用一种写法:Set set = new HashSet();这是为了提供兼容性。
2025-12-24 14:02:02
837
原创 《Effective Java》第25条:限制源文件为单个顶级类
原文P92:永远不要把多个顶级类或者接口放在一个源文件中。但是当再从 Dessert.java 源文件中定义 Utensil类 和 Dessert类,在idea中,程序就会编译出错,编译器会提醒你定义了多个Utensil 和Dessert类。正常情况下,在Utensil.java 源文件中定义 Utensil类 、在 Dessert.java 源文件中定义 Dessert类。Java允许我们在一个Java文件中,定义多个顶级类,并且可以正常编译和使用,但是这种方式是没有任何好处的,只会带来巨大的风险。
2025-12-18 13:55:41
255
原创 《Effective Java》第24条:静态成员类优于非静态成员类
上面的测试代码之所以输出的是 { },就是因为当调用 s.clear() 的时候,实际上执行的是HashMap内部类 keySet 类中的 clear() 方法,所以会将调用外部类(HashMap类)中的clear() 方法,将HashMap中的值全部清空。首先,前面的文字已经说过,非静态成员类(内部类)的实例会永久关联外围类的实例,因此内部类可以直接访问外围实例的所有成员(包括私有成员)。静态成员类(也叫静态内部类)是最简单的一种嵌套类,它声明在一个类的内部,可以访问外围类的所有成员,包括私有成员。
2025-12-12 16:17:22
598
原创 《Effective Java》第23条:类层次优于标签类
每种类型都有一种相关的独立的数据类型,允许程序员指明变量的类型,限制变量,并将参数输入到特殊的类型。先来认识一下什么叫标签类:它是一种设计模式,指一个类通过一个 “标签” 字段(如枚举、整数等)来区分不同的状态或类型,并根据标签的不同执行不同的逻辑。5、不灵活:要添加一种新类型,必须修改这个核心类的源代码,并排查所有条件语句进行更新,违反了“对扩展开放,对修改关闭”的原则。标签类正是对类层次的一种简单的仿效。总之:标签类的适用场景非常的少,当你想要实现一个标签类时,要考虑将它重构到一个层次结构中去。
2025-12-10 16:10:11
716
原创 《Effective Java》第22条:接口只用于定义类型
如果非 final 类(可被继承的类)实现了常量接口,其所有子类都会自动 “继承” 接口中的常量(尽管 Java 中接口常量是隐式public static final,子类并非真正继承,但可直接通过子类名访问)。2、常量属于枚举语义,使用枚举类型:如果常量是一组互斥的枚举项(比如状态、类型、选项等),且具有明确的 “枚举成员” 语义,应使用枚举类型而非普通常量,枚举不仅存储常量值,还能封装行为,是类型安全的常量集合。,类不实现接口,而是直接用接口名.常量名的方式来使用常量(博主常用),
2025-12-04 14:27:54
609
原创 《Effective Java》第21条:为后代设计接口
这是缺省方法的好处之一,但是,给现有的接口添加新方法还是充满风险的,因为实现该接口的类并不知道接口中已经增加了一个缺省方法,也没有经过实现类的许可,虽然这样可能不会导致什么问题,但是是一个隐患。5. 为了避免发生这种异常,维护人员必须要覆盖默认的 removeIf 实现,以及一些类似于 removeIf 的其他方法,以便在调用缺省实现之前执行必要的同步。默认方法是 “通用” 的,但集合的实现是多样的 —— 有些实现有特殊逻辑(比如同步、并发控制、自定义迭代规则),默认方法没法兼顾所有变体。
2025-12-04 14:23:33
644
原创 《Effective Java》第20条:接口优于抽象类
但是JDK源码中的 AbstractList 骨架实现类已经帮我们写好了很多的方法,只需要子类实现 get(int index) 和 size() 这两个最基本的方法(因为这两个方法没有通用实现,完全依赖具体列表的存储逻辑),基于 get 和 size,为 iterator、contains、indexOf、subList 等方法提供了默认实现(这些方法的逻辑是通用的),那么这个时候,我们只需要继承 AbstractList 骨架类,然后重写我们需要的方法即可。即使是使用组合方式,也不是一件容易的事情,
2025-11-28 15:05:32
881
原创 《Effective Java》第19条:要么设计继承并提供文档说明,要么禁止继承
对于每个公有的或受保护的方法或者构造器,它的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续处理过程的(所谓可覆盖的方法,是指非final的、公有的或受保护的)。更广义地说,即类必须在文档中说明,在哪些情况下它会调用可覆盖的方法。,因为父类构造器的执行顺序优先于子类构造器,如果父类构造器调用了可被覆盖的方法,那么就有可能在子类构造器还未执行的情况下,执行了子类的重写方法,如果该重写的方法依赖于子类构造器所执行的任何初始化工作,该方法将不会如预期般执行。
2025-11-26 13:36:05
1009
原创 《Effective Java》第18条:复合优先于继承
原文P72:这样得到的类将会非常稳固,它不依赖于现有类的实现细节,即使现有的类添加了新的方法,也不会影响新的类。在 ForwardingSet 类中可以看到,该类 复合 了 Set 接口,将里面所有的方法进行了转发,而不是重写,同时又实现了Set类,这一点很重要,后续所有继承自 ForwardingSet 类的子类,都是Set的子类,即,InstrumentedHashSet 也是一个Set集合,同时拥有了计数的功能。上面的这些问题,都是因为子类覆盖了超类的方法而导致的,如果不覆盖现有的方法可不可以呢?
2025-11-21 13:34:39
27
原创 《Effective Java》第17条:使可变性最小化
原文P69:许多不可变的类拥有一个或者多个非 final的域,它们在第一次被请求执行这些计算的时候,把一些开销昂贵的计算结果缓存在这些域中。声明所有的域都是 final的。而且,如果一个指向新创建实例的引用在缺乏同步机制的情况下,从一个线程被传递到另一个线程就必须确保正确的行为,即必须是线程安全的。当然,如果想让一个类成为“不可变类”,方法不仅仅有 使类是 final 的,还有另一种更灵活的方式:让类的所有构造器都变成私有的或者包级私有的,并添加公有的静态工厂来代替公有的构造器。声明所有的域都为私有的。
2025-11-19 15:41:48
459
原创 《Effective Java》第16条:要在公有类而非公有域中使用访问方法
原文P63:然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误。比如一个人(user),他的名字,年龄,性别,都是他的私有属性。所以:原文P63:毫无疑问,说到公有类的时候,坚持面向对象编程思想的看法是正确的:如果类可以在它所在的包之外进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。这种源码不值得效仿。书中最后给的例子(Time类),说明了,如果一个域是final的,那么将final域设置为public的,这种危害相对于小一些,但是这种做法依然是不提倡的!
2025-11-19 15:30:47
367
原创 《Effective Java》第15条:使类和成员的可访问性最小化
原文P61:公有类的实例域决不能是公有的。从上面的表格可以看出,类中的某个成员从 default 修饰符变为 protected 后,就突破了“包”的限制,可以在其他包中被使用,这个时候,该成员就变成了类的导出的API的一部分,应该永远得到支持。受保护的成员是类的导出的API的一部分,必须永远得到支持。也就是说,子类在覆盖超类方法的时候,该方法的访问级别不允许低于超类中的访问级别,同样的,如果实现一个接口,因为接口中的方法默认都是public的,所以子类中该接口的所有方法也必须都是public的。
2025-11-07 15:42:18
1011
原创 《Effective Java》第14条:考虑实现 Comparable 接口
许多程序员都喜欢这种方法的简洁性,在使用这个方法时,为了简洁起见,可以考虑使用Java的静态导入设施,通过静态比较器构造方法的简单的名称就可以对它们进行引用。以上的约定类似于前面第10条关于equals的约定,同样的对于equals的告诫也同样适用:“无法在用新的值组件扩展可实例化的类时,同时保持compareTo约定,除非愿意放弃面向对象的抽象优势”,即一个类如果被子类继承了,那么两个不同的子类调用父类的compareTo的时候,也可能会相等,就不满足上述的约定。上面的例子违反了传递性。
2025-10-31 16:38:18
698
原创 《Effective Java》第13条:谨慎的覆盖clone
原文P51:克隆复杂对象的最后一种办法是,先调用super.clone方法,然后把结果对象中的所有域都设置成它们的初始状态,然后调用高层的方法来重新产生对象的状态。原文P47:如果类的clone方法返回的实例不是通过调用super.clone方法获得,而是通过调用构造器获得,编译器就不会发出警告,但是该类的子类调用了super.clone方法,得到的对象就会拥有错误的类,并阻止了clone方法的子类正常工作。因此,上一段中讨论到的put(key,value)方法要么应是final的,要么应是私有的。
2025-10-24 15:25:03
657
原创 《Effective Java》第12条:始终要覆盖 toString
toString的通用约定指出,被返回的字符串应该是一个“简洁的但信息丰富,并且易于阅读的表达形式”。遵守 toString约定并不像遵守equals和hashCode 的约定(见第10条和第 11条)那么重要,但是,提供好的 tostring 实现可以使类用起来更加舒适,使用了这个类的系统也更易于调试。即:对于一些值类,我们有必要将toString以一种格式化的形式输出,如上例的电话号码(707-867-5309),这种方式易于阅读,也易于保存。即:对象的toString方法应该包含对象的所有必要信息。
2025-10-22 09:36:08
775
原创 《Effective Java》第11条:覆盖 equals 时总要覆盖 hashCode
原文P42:因为hashCode这个方法返回的结果是一个简单、确定的计算结果,它的输入只是PhoneNumber实例中的三个关键域,因此相等的 PhoneNumber 实例显然都会有相等的散列码。其实这就会有一个问题。1、在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对同一个对象的多次调用,hashcode方法都必须始终返回同一个值。(这句话的翻译我也是服了,不知所云,实际想表达的意思是,当多次运行某个程序的时候,每次运行产生的hashCode可以是不一致的。
2025-10-17 15:32:17
618
原创 《Effective Java》第10条:覆盖 equals 时请遵守通用规定
原文中提到的 “覆盖equals 方法而且这样做也使得这个类的实例可以被用作映射表(Map)的键(key),或者集合(Set)的元素,使映射或者集合表现出预期的行为”,这个的意思是,如果将person1、person2、person3放入作为Map的key 或者 放到Set集合中,实际 Map或者 Set集合中只会存在一个元素(因为,我们认为名字相同的人是“相等的”),但是要实现这个效果,仅仅只重写equals是不够的,必须还要重写hasCode方法。遗憾的是,因为兼容性的要求,这一行为无法被改变。
2025-10-14 15:24:38
638
原创 《Effective Java》第9条:try-with-resources 优先于 try-finally
例如,在firstLineOfFile方法中,如果底层的物理设备异常,那么调用 reaLine 就会抛出异常,基于同样的原因调用 close 也会出现异常。在日常编码中,我们还有一种方式来手动关闭资源,那就是 try-finally 的方式,那么这两种方式各自的优势是什么,什么场景下使用,我们今天就来讨论下。这里没法做试验演示,我们只需要知道这个问题就可以,由于finally块中的异常抹除了try块中的异常,会让我们误以为是在close的时候出现的问题。这种方式看起来没啥问题,但其实,这段代码是有问题的。
2025-09-25 09:26:04
643
原创 《Effective Java》第8条:避免使用终结方法和清除方法
它能确保资源在使用完毕后被自动释放,无需手动调用 close() 方法,从而简化代码并避免资源泄漏,但需要关闭的对象必须实现 AutoCloseable 接口,只有实现了 java.lang.AutoCloseable 接口(或其子接口 java.io.Closeable)的对象,才能作为资源在 try-with-resources 中使用。终结方法finalizer()并不是在对象不用之后就会立即执行的,它的执行是任意长时间的,甚至可能不执行,而且在不同的JVM中运行,其结果也会大相径庭。
2025-09-22 14:30:05
699
原创 《Effective Java》第7条:消除过期的对象引用
那如果这段代码反复的执行非常多的添加(push)和删除(pop)操作,就会有大量的类似于 “student4(赵六)” 这样的无用对象占据内存,最终可能会导致内存泄露,虽然说这种可能性很小(尤其是现在各种硬件性能过剩的情况下,可能性会更小)。在上面的例子中,我们将 student4 的类型设置为Student,如果 student4 被保留了下来,那么其中的 String name 对象,int age 对象,都会被保留,因为它们也是被 student4 强引用的对象。尽快地检测出程序中的错误总是有益的。
2025-09-18 11:37:16
608
原创 《Effective Java》第6条:避免创建不必要的对象
虽然被返回的 Set 实例一般是可改变的,但是所有返回的对象在功能上是等同的:当其中一个返回对象发生变化的时候,所有其他的返回对象也要发生变化,因为它们是由同一个Map实例支撑的。而这些对象功能方面完全一样,所以创建这些对象的动作全都是不必要的。相反,由于小对象的构造器只做很少量的显式工作,所以小对象的创建和回收动作是非常廉价的,特别是在现代的JVM实现上更是如此。1、本条目不是要你遇见对象就考虑避免创建多重对象,而是要视情况而定,对于小对象而言,它的创建和回收是非常廉价的,现代JVM已经优化的很好了。
2025-09-10 15:58:51
632
原创 《Effective Java》第5条:优先考虑依赖注入来引用资源
带有 Supplier的方法,通常应该限制输入工厂的类型参数使用有限制的通配符类型(即不要使用Object这种类型,这种没有限制),详见第31条,以便客户端能够传入一个工厂,来创建指定类型的任意子类型。原文P17:满足该需求的最简单的模式是:当创建一个新的实例时,就将该资源传到构造器中。这是依赖注入(dependencyinjection)的一种形式:词典(dictionary)是拼写检查器的一个依赖(dependency),在创建拼写检查器时就将词典注入(injected)其中。(Spring用的最多)
2025-09-05 11:31:06
822
原创 《Effective Java》第4条:通过私有构造器强化不可实例化的能力
也就是说,弊端就是被私有化构造器的类,不能被继承了,相当于是违背了Java的三大思想中的一个,不过没关系,我们之所以这么用,目的也不是为了让子类继承,更多的是需要一个工具来帮我们做事情,所以,该怎么用就怎么用吧!比如上面的例子,电商平台货物的状态,也可以通过接口来写,而且更加方便,我也更加推荐大家使用这种方式来写公共的常量类,因为接口里的常量默认都是public static final的,不用再去写了,如下代码。其次,抽象类还会被误解为是一个专门用来被继承的类,实际上我们的目的并不是需要它被继承。
2025-09-02 10:54:33
536
原创 《Effective Java》第3条:用私有构造器或者枚举类型强化 Singleton 属性
原文P15:这种方法在功能上与公有域方法相似,但更加简洁,无偿地提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。这类对象的多个实例之间没有差异——无论创建多少个,它们的功能完全一致,此时重复创建实例只会浪费内存资源,如 StringUtils 字符串处理工具,就是单例的,可以看源码,发现 StringUtils 类中除了构造方法外,其他所有方法都是 static 的,也就是说是单例的。好处就是,简化代码,提高可读性,延迟执行等等。②公有的静态成员是个静态工厂方法;
2025-08-25 08:57:42
569
原创 《Effective Java》第2条:遇到多个构造器参数时要考虑使用构建器
原文P13:注意,每个子类的构建器中的build方法,都声明返回正确的子类,NyPizza.Builder的build方法返回NyPizza,而Calzone.Builder中的则返回Calzone,在该方法中,子类方法声明返回超级类中声明的返回类型的子类型,这被称作协变返回类型。对比完setter模式 和 构建器之后,我们知道了,构建器有很多好处是setter没有的,其实不光在这种平行层次结构中构建器有好处,在类层次结构中,构建器模式也适用(其中用户的用户名,密码是必填项,其余的是非必填项。
2025-08-19 15:14:08
609
原创 《Effective Java》第1条:用静态工厂方法代替构造器
该例子中,Man类 和 Woman类 都变成了Person 的子类,getAnyone方法可以返回任意的一个子类,但是Main方法中,没有做任何的修改,如果此时又有一个Badman类实现了Person,那么只需要在Person中加入一个静态成员变量和get方法即可。但现在 这个外星人类是不存在的。像是上面的例子,实现Person的两个类都是内部类,所以Person的构造器可以是private的,如果其中有一个类不是内部类,那么Person的构造器就不能是Persion的,否则就不能被子类继承。
2025-08-15 17:47:50
607
原创 《Effective Java》第0条:写在前面,用一年时间来深度解读《Effective Java》这本书
【摘要】博主计划用一年时间深度解读《Effective Java》一书,每周发布1-2个条目的分析文章。由于书中部分内容较难理解,博主将通过反复研读和代码实践进行解读。采用俞黎敏翻译版,欢迎读者指正任何问题,并可免费获取电子版PDF。该系列将按顺序持续更新,旨在与读者共同学习这本Java经典著作。
2025-08-15 17:37:27
167
原创 Vue + el-ui table 内嵌 input 调用 focus 方法无效;this.$refs.xxx.focus()方法无效
我又试了一下,当不把标签放在里的时候,比如正常表单(ref不是通过动态赋值)的时候,这段代码是完全没有问题的。如图,当在第一行 9999 处敲击回车之后,控制台打印出了this.$refs的所有组件,也打印了定位前和定位后的log日志,且没有报错,说明我们的代码是正确执行了的。学号HTML,JS,CSS吧,无论框架怎么变,底层都是这东西,当发现框架不支持的时候,可以考虑考虑原生的DOM实现。a.在表格编辑态的时候,可以在①处敲击“回车键”,光标能跳转到②处。
2023-09-18 13:44:32
2703
4
原创 Git拉取项目There is no tracking information for the current branch.(idea拉取项目master has no tracked brach)
There is no tracking information for the current branchmaster has no tracked brach
2023-09-12 08:41:04
470
原创 JAVA获取一台机器的MAC地址
前置条件:首先要能够ping通要获取MAC地址的电脑A(如果不能ping通可能原因是防火墙没关)获取MAC地址原理:1、首先获取A的IP地址,2、然后ping这个IP,ping通之后,3、然后再调用”arp -a IP地址”命令,获取到A的MAC地址(此时获取到的MAC地址是字母都是小写的)4、将小写字母转为大写代码: /** * 1、首先获取A的IP地址 * @param request * @return ip * @throws ...
2020-12-24 15:15:49
599
原创 Oracle存储过程实现批量模拟数据(表名做参数 + if,for条件判断)
需求:要往数据库表里造一批数据,用于测试人员测试,测试人员通过修改开始时间和结束时间来模拟这段时间的数据(数据时间间隔也作为参数配置)。约束:1、使用存储过程的方式。2、表名称也要作为一个参数传入。3、以下测试可能不太符合真实业务,仅仅是为了展示:表名做参数 if条件,for循环的用法。环境:数据库:Oracle 11g 可视化工具:PL/SQL步骤1:数据库中有这样一张表(如图)记录了一个人每隔一段时间的身高变化(假设这个人一直长高)。步骤2:想模拟一段时间的测试数据,开始...
2020-12-17 10:48:41
1170
原创 oracle + plsql定时执行任务 (定时器+简单的存储过程)
1、定义一个存储过程(这是最简单的形式,复杂的形式有输入输出参数。详见:https://www.cnblogs.com/Zeros/p/8081080.html)CREATE OR REPLACE PROCEDURE timedTask iS -- timedTask 为存储过程的名字BEGIN --开始写sql语句(根据自己的需要去写)DELETE test_table2;INSERT INTO Test_table2 SELECT * FROM Test_ta...
2020-12-02 17:14:35
6976
原创 SpringBoot集成Thymeleaf
1、首先引入Thymeleaf的jar包2、新建一个controller来测试Thymeleaf注意点已经在图中标出。 a、首先注解不能是@RestController。 b、要加入一个Model的参数 c、return的字符串是html文件的名字,不用加.html3、新建一个index.html页面来显示(注意Thymeleaf语法,参考:https://www.cnblogs.com/itdragon/archive/2018/04/13/8...
2020-12-02 16:59:20
180
原创 SSM集成Shiro实现用户登录认证
Shiro的核心API:整合步骤:1、首先在pom.xml中引入shiro-spring的jar包<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring --><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</ar..
2020-12-02 16:54:51
430
原创 SpringBoot集成Kafka(生产者和消费者都是SpringBoot服务)
1、首先在 pom.xml 引入依赖<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency>2、配置文件application.properties中配置生产者###kafka## producerspring.kafka....
2020-12-02 16:47:05
644
原创 idea关闭tab标签页返回上次打开的页面
由于之前使用eclipse的习惯,在当前A页面按住ctrl跳转到另一个java文件(B页面),再关闭B页面就会回到A页面。但是idea默认的不是这样的,默认的总是关闭页面之后打开该页面相邻的左侧界面,下面就来描述怎么修改。方法很简单:File -> Settings -> Editor -> General -> Editor Tabs :...
2020-10-30 09:56:13
3092
原创 使用MyBatis的databaseIdProvider多数据库标识(SSM项目和非SSM项目)
场景:公司要开发一个XX系统,同时部署到两个现场,但是A现场用户要求使用MySQL数据库。B现场用户要求使用Oracle数据库。这咋整,不能再把语句删了重写吧。Mybatis提供了一种解决方案,使用databaseIdProvider标识多个数据库。这是我找到的两个比较好的资源,都测试过,好用。感谢两位作者的分享1、非SSM项目(Java集成Mybatis)https://www.cnblogs.com/hellowhy/p/9676037.html2、SSM项目https://my.o
2020-09-07 16:11:06
260
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅