首页 文章 精选 留言 我的

精选列表

搜索[java],共10000篇文章
优秀的个人博客,低调大师

Java入门提高篇】Day15 Java泛型再探——泛型通配符及上下边界

上篇文章中介绍了泛型是什么,为什么要使用泛型以及如何使用泛型,相信大家对泛型有了一个基本的了解,本篇将继续讲解泛型的使用,让你对泛型有一个更好的掌握和更深入的认识。 上篇中介绍完泛型之后,是不是觉得泛型挺好用的?既消除了Object的不安全类型转化,又可以很方便的进行类型对象的存取,但是,等一下,有没有考虑到这样的情况。 我们先定义一个水果类: public class Fruit { private String name; public Fruit(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 然后再定义一个苹果类: public class Apple extends Fruit{ public Apple(String name) { super(name); } } 接下来定义一个泛型容器: public class GenericHolder<T> { private T obj; public GenericHolder(){} public GenericHolder(T obj){ this.obj = obj; } public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } 接下来开始我们的测试: public class Test { /** * 吃水果 * @param fruitHolder */ public static void eatFruit(GenericHolder<Fruit> fruitHolder){ System.out.println("我正在吃 " + fruitHolder.getObj().getName()); } public static void main(String args[]){ //这是一个贴了水果标签的袋子 GenericHolder<Fruit> fruitHolder = new GenericHolder<Fruit>(); //这是一个贴了苹果标签的袋子 GenericHolder<Apple> appHolder = new GenericHolder<Apple>(); //这是一个水果 Fruit fruit = new Fruit("水果"); //这是一个苹果 Apple apple = new Apple("苹果"); //现在我们把水果放进去 fruitHolder.setObj(fruit); //调用一下吃水果的方法 eatFruit(fruitHolder); //贴了水果标签的袋子放水果当然没有问题 //现在我们把水果的子类——苹果放到这个袋子里看看 fruitHolder.setObj(apple); //同样是可以的,其实这时候会发生自动向上转型,apple向上转型为Fruit类型后再传入fruitHolder中 //但不能再将取出来的对象赋值给redApple了 //因为袋子的标签是水果,所以取出来的对象只能赋值给水果类的变量 //无法通过编译检测 redApple = fruitHolder.getObj(); eatFruit(fruitHolder); //放苹果的标签,自然只能放苹果 appHolder.setObj(apple); // 这时候无法把appHolder 传入eatFruit // 因为GenericHolder<Fruit> 和 GenericHolder<Apple>是两种不同的类型 // eatFruit(appHolder); } } 运行结果: 我正在吃 水果 我正在吃 苹果 在这里,我们往eatFruit方法里传入fuitHolder的时候,是可以正常编译的,但是如果将appHolder传入,就无法通过编译了,因为作为参数时,GenericHolder<Fruit> 和 GenericHolder<Apple>是两种不同的类型,所以无法通过编译,那么问题来了,如果我想让eatFruit方法能同时处理GenericHolder<Fruit> 和 GenericHolder<Apple>两种类型怎么办?而且这也是很合理的需求,毕竟Apple是Fruit的子类,能吃水果,为啥不能吃苹果???如果要把这个方法重载一次,未免也有些小题大做了(而且事实上也无法通过编译,具体原因之后会有说明)。 在代码的逻辑里: 苹果 IS-A 水果 装苹果的盘子 NOT-IS-A 装水果的盘子 这个时候,泛型的边界符就有它的用武之地了。我们先来看效果: public class Test { /** * 吃水果 * @param fruitHolder */ public static void eatFruit(GenericHolder<? extends Fruit> fruitHolder){ System.out.println("我正在吃 " + fruitHolder.getObj().getName()); } public static void main(String args[]){ //这是一个贴了水果标签的袋子 GenericHolder<Fruit> fruitHolder = new GenericHolder<Fruit>(); //这是一个贴了苹果标签的袋子 GenericHolder<Apple> appHolder = new GenericHolder<Apple>(); //这是一个水果 Fruit fruit = new Fruit("水果"); //这是一个苹果 Apple apple = new Apple("苹果"); //现在我们把水果放进去 fruitHolder.setObj(fruit); //调用一下吃水果的方法 eatFruit(fruitHolder); //放苹果的标签,自然只能放苹果 appHolder.setObj(apple); // 这时候可以顺利把appHolder 传入eatFruit eatFruit(appHolder); } } 运行结果: 我正在吃 水果 我正在吃 苹果 这里我们只是使用了一点小小的魔法,把参数类型改成了GenericHolder<? extends Fruit>,这样就能将GenericHolder<Apple>类型的参数顺利传入了,怎么样?很好用吧,这就是泛型的边界符,用<? extends Fruit>的形式表示。边界符的意思,自然就是定义一个边界,这里用?表示传入的泛型类型不是固定类型,而是符合规则范围的所有类型,用extends关键字定义了一个上边界,也就是说这里的?可以代表任何继承于Fruit的类型,你也许会问,为什么是上边界,好问题,一图胜千言: 从这个图可以很好的看出这个“上边界”的概念了吧。有上边界,自然有下边界,泛型里使用形如<? super Fruit>的方式使用下边界,此时,?只能代表Fruit及其父类。 (这两个图是抠过来的,不要骂我懒。) 这两种方式基本上解决了我们之前的问题,但是同时,也有一定的限制。 1.上界<? extends T>不能往里存,只能往外取 不要太疑惑,其实很好理解,因为编译器只知道容器里的是Fruit或者Fruit的子类,但不知道它具体是什么类型,所以存的时候,无法判断是否要存入的数据的类型与容器种的类型一致,所以会拒绝set操作。 2.下界<? super T>往外取只能赋值给Object变量,不影响往里存 因为编译器只知道它是Fruit或者它的父类,这样实际上是放松了类型限制,Fruit的父类一直到Object类型的对象都可以往里存,但是取的时候,就只能当成Object对象使用了。 所以如果需要经常往外读,则使用<? extends T>,如果需要经常往外取,则使用<? super T>。 至此,本篇讲解完毕,欢迎大家继续关注! 真正重要的东西,用眼睛是看不见的。

优秀的个人博客,低调大师

jsoup 1.22.2 发布,Java HTML 解析器

jsoup 1.22.2 现已发布,对库进行了多项修复和改进。它使遍历 DOM 时编辑 DOM 的操作更加可预测,使用更新的元素和更佳的文本边界更新了默认的 HTML 标签定义,并提高了解析和 HTTP 传输的可靠性。此版本还修复了清理、流解析、XML 文档类型处理和 Android 打包方面的一些特殊情况。 改进 扩展并明确了NodeTraversor在NodeVisitor.head()期间对就地 DOM 重写的支持。当前节点的编辑操作(如移除、替换和解包)现在能够以更可预测的方式恢复,同时遍历仍保持在原始根子树内。这使得编写 single-pass tree cleanup 和规范化访问器更加容易,例如在遍历 DOM 时展开展示元素或替换文本节点#2472 文档:明确了已配置的Cleaner实例可在并发线程间复用,并且共享Safelist实例在使用过程中不应被修改。#2473 更新了当前 HTML 元素的默认 HTML TagSet:新增了 dialog、search、picture 和 slot 标签;将 ins、del、button、audio、video 和 canvas 默认设为内联(Tag#isInline(),与规范中的表述保持一致);并通过新的 Tag.TextBoundary 选项,为控件和嵌入对象添加了可读的 Element.text() 边界。此举改善了代码美观度,并防止规范化文本将相邻单词合并在一起。#2493 错误修复 Android (R8/ProGuard):新增一条规则,当可选的re2j依赖项不存在时将其忽略。#2459 修复了 1.21.2 版本中的一个NodeTraversor回归问题,该问题会导致在head()期间移除或替换当前节点时,可能会重新访问被替换的节点并导致无限循环。遍历文档现已明确说明当前遍历过程中会访问哪些插入的节点。#2472 在字符集嗅探过程中,即使调用available()抛出IOException(如在 JDK 8 的HttpURLConnection中所见),解析操作也不会再失败。#2474 Cleaner在清理或验证文档时,不再将输入文档中的相对 URL 属性转换为绝对 URL。URL 规范化现在仅应用于清理后的输出,且Safelist.isSafeAttribute()方法不再产生副作用。#2475 当输入文档保留属性大小写时,Cleaner不再复制强制属性。现在,在经过清理的输出中,不区分大小写的源属性将被强制属性替换。#2476 如果配置了按请求设置的 SOCKS 代理,jsoup 现在会避免使用 JDK HttpClient,因为 JDK 会无提示地忽略该代理并尝试直接连接。此类请求现将回退至支持 SOCKS 的旧版 HttpURLConnection 传输机制。#2468 若未声明字符集,且初始 5 KB 的字符集检测在流解析开始前已完全读取并关闭输入流,Connection.Response.streamParser()和DataUtil.streamParser(Path, ...)可能会在处理小型输入时失败。#2483 在 XML 模式下,包含内部子集的文档类型声明(例如<!DOCTYPE root [<!ENTITY name "value">]>)现在能够正确地进行往返传输。子集仅作为原始文本保留;实体不会被展开,外部 DTD 也不会被加载。#2486 Build Changes 已将集成测试服务器从 Jetty 迁移到 Netty,能够持续支持最低 JDK 目标版本 (8)。#2491 更新说明:https://github.com/jhy/jsoup/releases/tag/jsoup-1.22.2

优秀的个人博客,低调大师

jsoup 1.21.2 发布,Java HTML 解析器

jsoup 1.21.2 现已发布,新增了对 HTTP/2 连接中自定义SSLContext的支持,并提升了属性中用户数据处理方式的一致性。此外,它还提升了 DOM 操作和片段解析的性能,并修复了流解析、遍历、克隆和并发读取中的一些边缘情况。 变化 已弃用的内部(但可见)方法Normalizer#normalize(String, bool)和Attribute#shouldCollapseAttribute(Document.OutputSettings)。这些将在未来的版本中删除。 已弃用Connection#sslSocketFactory(SSLSocketFactory),建议使用新的Connection#sslContext(SSLContext)。使用sslSocketFactory将强制使用旧HttpUrlConnection实现,该实现不支持 HTTP/2。#2370 改进 当进行 pretty-printing 时,如果有连续的文本节点(通过 DOM 操作),则它们之间的非重要空白将被折叠。#2349。 更新Connection.Response#statusMessage()为在使用HttpClient实现时返回一个简单的可记录字符串消息(例如“OK”),否则不会返回任何服务器设置的状态消息。#2356 Attributes#size()和Attributes#isEmpty()现在​​​​​​​将所有内部属性(例如用户数据)排除在其计数之外。这与属性的序列化输出和迭代器保持一致。#2369 添加Connection#sslContext(SSLContext)以向请求提供自定义 SSL (TLS) 上下文,同时支持HttpClient和旧版HttUrlConnection实现。#2370 针对 DOM 操作方法的性能优化,包括在多次移除元素的第一个子元素(element.child(0).remove()),以及使用Parser#parseBodyFragement()解析大量直接子元素时的情景。#2373。​​​​​​​ 错误修复 当从 InputStream 进行解析并且多字节字符恰好跨越缓冲区边界时,流将无法完全读取。#2353。 在NodeTraversor中,如果在head()调用期间删除了最后一个子元素,则父元素会被访问两次。#2355。 克隆具有 Attributes 对象的 Element 会向该克隆添加一个空的内部用户数据属性,这会导致Attributes#size()和Attributes#isEmpty()出现意外结果。#2356 在多线程应用程序中,多个线程同时调用同一元素Element#children()时,该方法生成内部子元素缓存(其子节点的筛选视图)时可能会发生竞争条件。由于 DOM 对象的并发读取应该是线程安全的,无需外部同步,因此该方法已更新为原子执行。#2366 格式错误的 HTML 可能会在 adoption agency 期间抛出 IndexOutOfBoundsException。#2377。 详情可查看:https://jsoup.org/news/release-1.21.2

优秀的个人博客,低调大师

jsoup 1.21.1 发布,Java HTML 解析器

jsoup 1.21.1 现已发布。此版本具有强大的全新节点选择功能,可让用户使用 CSS 选择器锁定特定的 DOM 节点(例如注释和文本节点)、通过新的 TagSet 回调系统进行动态标签自定义,并通过简化的属性转义增强了对突变 XSS 攻击的防御能力。 此版本还默认提供 HTTP/2 支持,并进行了多项 API 改进以提升开发者体验,并修复了多个 edge-case parsing 问题。 Changes 删除了以前弃用的方法。#2317 由于:matchTextpseduo-selector 对 DOM 的副作用,已将其弃用;改用新的::textnodeselector和 Element#selectNodes(String css, Class<T> type)方法。#2343 已弃用Connection.Response#bufferUp(),以代替Connection.Response#readFully(),后者会抛出一个已检查的 IOException。 已弃用的内部方法Validate#ensureNotNull(Object)(由 typedValidate#expectNotNull(T)替代);来自 Attribute 和 Node 的受保护 HTML 附加程序。 如果你碰巧正在使用任何已弃用的方法,官方建议立即借此机会迁移它们,因为它们将在未来的版本中被删除。 Improvements 增强了Selector,支持直接匹配注释和文本节点等节点。#2324 新增TagSet#onNewTag(Consumer<Tag> customizer):注册一个回,当每个新的或克隆的标签插入到集合中时,都会调用该回调函数。该函数支持动态调整标签选项(例如,将所有自定义标签标记为自闭合,或将给定命名空间中的所有内容标记为保留空格)。#2330 使TokenQueue和CharacterReader可自动关闭,以确保它们将缓冲区释放回缓冲池,以供以后重用。 添加了Selector#evaluatorOf(String css),以更清晰的方式从 CSS 查询中获取评估器。这是QueryParser.parse(String css)的别名。 可以将外部命名空间(例如 SVG)中的自定义标签(通过TagSet定义)配置为数据标签进行解析。 添加NodeVisitor#traverse(Node)以简化节点遍历调用(相对于导入NodeTraversor)。 更新了默认用户代理字符串以提高兼容性。#2341 HTML 解析器现在允许为已知标签自定义特定的文本数据类型 (Data、RcData)。(之前此功能仅支持自定义标签。)#2326 添加了Connection.Response#readFully(),以替代Connection.Response#bufferUp(),并明确了 IOException。同样,添加Connection.Response#readBody()代替Connection.Response#body()。已弃用Connection.Response#bufferUp()。#2327 序列化 HTML 时,属性中的<和>字符现在会被转义。这有助于防止一类变异 XSS 攻击。#2337 已更改Connection为优先使用 JDK 的 HttpClient 而非 HttpUrlConnection(如果可用),以默认启用 HTTP/2 支持。用户可以通过禁用-Djsoup.useHttpClient=false关闭该功能。#2340 Bug Fixes svg外部上下文中的script内容应被解析为脚本数据,而非文本。#2320 Tag#isFormSubmittable()正在更新标签的选项。#2323 当文本跟在块元素中的内联元素之后时,HTML pretty-printer会错误地修剪空格。#2325 名称中带有连字符或其他非字母字符的自定义标签现在可以正确用作 Data 或 RcData 标签。它们的结束标签现在也能正确标记。#2332 克隆元素时,克隆将保留源的缓存子元素列表(如果有),这可能导致在修改克隆的子元素时出现不正确的结果。#2334 更新说明:https://jsoup.org/news/release-1.21.1

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册