![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java 学习
文章平均质量分 73
iHero
这个作者很懒,什么都没留下…
展开
-
【Java】集合 之 使用 Set
我们知道,Map用于存储key-value的映射,对于充当key的对象,是不能重复的,并且,不但需要正确覆写equals()方法,还要正确覆写hashCode()方法。如果我们只需要存储不重复的key,并不需要存储映射的value,那么就可以使用Set。Set用于存储不重复的元素集合,它主要提供以下几个方法:将元素添加进将元素从Set<E>实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素。因为放入Set的元素和Map的key类似,都要正确实现equals()原创 2023-12-07 17:26:04 · 395 阅读 · 0 评论 -
【Java】集合 之 使用 Properties
在编写应用程序的时候,经常需要读写配置文件。配置文件的特点是,它的Key-Value一般都是类型的,因此我们完全可以用来表示它。因为配置文件非常常用,所以Java集合库提供了一个Properties来表示一组“配置”。由于历史遗留原因,Properties内部本质上是一个Hashtable,但我们只需要用到Properties自身关于读写配置的接口。读取配置文件用Properties读取配置文件非常简单。Java默认配置文件以为扩展名,每行以key=value表示,以#课开头的是注释。调用。原创 2023-12-07 10:22:28 · 815 阅读 · 0 评论 -
【Java】集合 之 使用 TreeMap
我们已经知道,HashMap是一种以空间换时间的映射表,它的实现原理决定了内部的Key是无序的,即遍历HashMap的Key时,其顺序是不可预测的(但每个Key都会遍历一次且仅遍历一次)。还有一种Map,它在内部会对Key进行排序,这种Map就是SortedMap。注意到SortedMap是接口,它的实现类是TreeMap。保证遍历时以Key的顺序来进行排序。例如,放入的Key是"apple""pear""orange",遍历的顺序一定是"apple""orange""pear",因为String使用。原创 2023-12-04 10:19:34 · 525 阅读 · 0 评论 -
【Java】集合 之 使用EnumMap
因为HashMap是一种通过对key计算hashCode(),通过空间换时间的方式,直接定位到value所在的内部数组的索引,因此,查找效率非常高。如果作为key的对象是enum类型,那么,还可以使用Java集合库提供的一种EnumMap,它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。我们以DayOfWeek使用EnumMap的时候,我们总是用Map接口来引用它,因此,实际上把。原创 2023-12-04 10:08:47 · 427 阅读 · 0 评论 -
【Java】集合 之 编写equals和hashCode
我们知道Map是一种键-值映射表,可以通过key快速查找对应的value。以HashMap之所以能根据key直接拿到value,原因是它内部通过空间换时间的方法,用一个大数组存储所有value,并根据key直接计算出value如果key的值为"a",计算得到的索引总是1,因此返回,如果key的值为"b",计算得到的索引总是5,因此返回value为,这样,就不必遍历整个数组,即可直接读取key对应的value。当我们使用key存取value的时候,就会引出一个问题:我们放入Map的key是字符串"a"原创 2023-12-01 10:43:14 · 886 阅读 · 0 评论 -
【Java】集合 之 使用 Map
我们知道,List是一种顺序列表,如果有一个存储学生Student实例的List,要在List中根据name查找某个指定的Student的分数,应该怎么办?最简单的方法是遍历List并判断name这种需求其实非常常见,即通过一个键去查询对应的值。使用List来实现存在效率非常低的问题,因为平均需要扫描一半的元素才能确定,而Map这种键值映射表的数据结构,作用就是能高效通过key快速查找value(元素)。用Map来实现根据name查询某个StudentMap是一种键-值映射表,当我们调用。原创 2023-11-30 10:30:14 · 608 阅读 · 0 评论 -
【Java】集合 之 编写 equals 方法
List还提供了方法来判断List是否包含某个指定元素。此外,方法可以返回某个元素的索引,如果元素不存在,就返回-1。这里我们注意一个问题,我们往List中添加的 “C” 和调用传入的"C"是不是同一个实例?如果这两个"C"不是同一个实例,这段代码是否还能得到正确的结果?因为我们传入的是,所以一定是不同的实例。结果仍然符合预期,这是为什么呢?因为List内部并不是通过==判断两个元素是否相等,而是使用equals()方法判断两个元素是否相等,例如contains()因此,要正确使用List的。原创 2023-11-30 09:58:19 · 790 阅读 · 0 评论 -
【Java】集合 之 使用List
在集合类中,List是最基础的一种集合:它是一种有序列表。List的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,List的索引和数组一样,从0开始。数组和List类似,也是有序结构,如果我们使用数组,在添加和删除元素的时候,会非常不方便。这个“删除”操作实际上是把’C’后面的元素依次往前挪一个位置,而“添加”操作实际上是把指定位置以后的元素都依次向后挪一个位置,腾出来的位置给新加的元素。这两种操作,用数组实现非常麻烦。原创 2023-09-27 16:08:47 · 679 阅读 · 0 评论 -
【Java】集合 之 Java集合简介
什么是集合(Collection)?集合就是“由若干个确定的元素所构成的整体”。在数学中,我们经常遇到集合的概念。例如:有限集合:一个班所有的同学构成的集合;一个网站所有的商品构成的集合;无限集合:全体自然数集合:1,2,3,……有理数集合;实数集合;为什么要在计算机中引入集合呢?这是为了便于处理一组类似的数据,例如:计算所有同学的总成绩和平均成绩;列举所有的商品名称和价格;……原创 2023-09-26 17:06:08 · 122 阅读 · 0 评论 -
【Java】泛型 之 泛型和反射
Java的部分反射API也是泛型。Class调用Class的方法返回的Class类型是构造方法使用泛型数组要特别小心,因为数组实际上在运行期没有泛型,编译器可以强制检查变量ps,因为它的类型是泛型数组。但是,编译器不会检查变量arr,因为它不是泛型数组。上面的代码中,由于拿不到原始数组的引用,就只能对泛型数组ps进行操作,这种操作就是安全的。谨慎使用泛型可变参数似乎可以安全地创建一个泛型数组。但实际上,这种方法非常危险。直接调用似乎没有问题,但是在另一个方法中,我们返回一个泛型数组就会产生。原创 2023-09-25 17:20:11 · 252 阅读 · 0 评论 -
【Java】泛型 之 super通配符
extendssupe不是的子类。传入是允许的,但是传入是不允许的。和extends通配符相反,这次,我们希望接受类型,以及,因为Number和Object是Integer的父类,和实际上允许接受Integer类型。我们使用super注意到表示,方法参数接受所有泛型类型为Integer或Integer父类的Pair类型。考察的setFirst()因此,可以安全地传入Integer类型。再考察的getFirst()这里注意到我们无法使用Integer类型来接收getFirst()原创 2023-09-25 16:53:27 · 628 阅读 · 0 评论 -
【Java】泛型 之 extends通配符
不是的子类。假设我们定义了Pair原创 2023-09-25 15:29:33 · 421 阅读 · 0 评论 -
【Java】泛型 之 擦拭法
泛型是一种类似”模板代码“的技术,不同语言的泛型实现方式不一定相同。Java语言的泛型实现方式是擦拭法(所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。例如,我们编写了一个泛型类Pair而虚拟机根本不知道泛型。所以,Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。原创 2023-09-22 15:34:32 · 510 阅读 · 0 评论 -
【Java】泛型 之 编写泛型
写泛型类比普通类要复杂。通常来说,泛型类一般用在集合类中,例如,我们很少需要编写泛型类。如果我们确实需要编写一个泛型类,那么,应该如何编写它?可以按照以下步骤来编写一个泛型类。String然后,标记所有的特定类型,这里是String最后,把特定类型String替换为T,并申明熟练后即可直接从T开始编写。原创 2023-09-22 15:18:42 · 417 阅读 · 0 评论 -
【Java】泛型 之 使用泛型
使用ArrayList时,如果不定义泛型类型时,泛型类型实际上就是Object此时,只能把当作Object使用,没有发挥泛型的优势。当我们定义泛型类型后,List的泛型接口变为强类型L当我们定义泛型类型后,List的泛型接口变为强类型编译器如果能自动推断出泛型类型,就可以省略后面的泛型类型。编译器看到泛型类型就可以自动推断出后面的的泛型类型必须是。原创 2023-09-22 14:31:26 · 104 阅读 · 0 评论 -
【Java】泛型 之 什么是泛型
泛型是一种“代码模板”,可以用一套代码套用各种类型。在讲解什么是泛型之前,我们先观察Java标准库提供的ArrayList,它可以看作“可变长度”的数组,因为用起来比数组更方便。实际上ArrayList内部就是一个Object[]这样一来,存入的必须是String,取出的也一定是String问题暂时解决。然而,新的问题是,如果要存储Integer,还需要为Integer单独编写一种ArrayList实际上,还需要为其他所有class单独编写一种ArrayList这是不可能的,JDK的class。原创 2023-09-21 17:11:19 · 111 阅读 · 0 评论 -
【Java】注解 之 处理注解
Java的注解本身对代码逻辑没有任何影响。根据@RetentionSOURCECLASSclassJVMRUNTIMEJVM如何使用注解完全由工具决定。SOURCE类型的注解主要由编译器使用,因此我们一般只使用,不编写。CLASS类型的注解主要由底层工具库使用,涉及到class的加载,一般我们很少用到。只有RUNTIME类型的注解不但要使用,还经常需要编写。因此,我们只讨论如何读取RUNTIME类型的注解。因为注解定义后也是一种class,所有的注解都继承自,因此,读取注解,需要使用反射API。原创 2023-09-21 14:44:25 · 90 阅读 · 0 评论 -
【Java】注解 之 定义注解
Java语言使用@interface语法来定义注解注解的参数类似无参数方法,可以用default设定一个默认值(强烈推荐)。最常用的参数应当命名为value。原创 2023-09-20 17:05:34 · 141 阅读 · 0 评论 -
【Java】注解 之 使用注解
注释会被编译器直接忽略,注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。原创 2023-09-20 16:36:08 · 78 阅读 · 0 评论 -
【Java】反射 之 动态代理
我们来比较Java的class和interface的区别:可以实例化class(非abstract);不能实例化interface。有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?这是可能的,因为Java标准库提供了一种动态代理的机制:可以在运行期动态创建某个interface的实例。什么叫运行期动态创建?听起来好像很复杂。所谓动态代理,是和静态相对应的。我们来看静态代码怎么写:这种方式就是我们通常编写代码的方式。原创 2023-09-08 16:04:07 · 191 阅读 · 0 评论 -
【Java】反射 之 获取继承关系
当我们获取到某Class还可以用实例的getClass()最后一种获取Class的方法是通过这三种方式获取的Class实例都是同一个实例,因为JVM对每个加载的Class只创建一个Class实例来表示它的类型。获取父类的Class运行上述代码,可以看到,Integer的父类类型是NumberNumber的父类是ObjectObject的父类是null。除Object外,其他任何非interface的Class都必定存在一个父类类型。获取interface。原创 2023-09-07 17:27:10 · 197 阅读 · 0 评论 -
【Java】反射 之 调用构造方法
如果通过反射来创建新的实例,可以调用Class提供的调用的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过来调用。为了调用任意的构造方法,Java的反射API提供了对象,它包含一个构造方法的所有信息,可以创建一个实例。对象和Method获取某个public的;:获取某个;:获取所有public的:获取所有注意总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。调用非public的时,必须首先通过设置允许访问。可能会失败。原创 2023-08-25 18:30:28 · 407 阅读 · 0 评论 -
【Java】反射 之 调用方法
我们已经能通过Class实例获取所有Field对象,同样的,可以通过Class实例获取所有Method信息。Class类提供了以下几个方法来获取MethodpublicMethodMethodpublicMethodMethod上述代码首先获取Student的Class实例,然后,分别获取public方法、继承的public方法以及private方法,打印出的Method一个MethodgetName()原创 2023-08-25 18:15:51 · 983 阅读 · 0 评论 -
【Java】反射 之 访问字段
对任意的一个Object实例,只要我们获取了它的Class,就可以获取它的一切信息。我们先看看如何通过Class实例获取字段信息。Class上述代码首先获取Student的Class实例,然后,分别获取public字段、继承的public字段以及private字段,打印出的Field一个FieldgetName():返回字段名称,例如,“name”;getType():返回字段类型,也是一个Class实例,例如,;:返回字段的修饰符,它是一个int,不同的bit表示不同的含义。以String类的。原创 2023-08-18 14:42:19 · 163 阅读 · 0 评论 -
【Java】反射 之 Class类
反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息。怎么办?有童鞋会说:强制转型啊!强制转型的时候,你会发现一个问题:编译上面的代码,仍然需要引用Person类。不然,去掉import语句,你看能不能编译通过?所以,反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。原创 2023-08-11 07:25:17 · 105 阅读 · 0 评论 -
【Java】JVM GC配置指南
以下所有优化全部基于JDK8版本,强烈建议低版本升级到JDK8,并尽可能使用update_191以后版本。原创 2023-08-10 16:07:45 · 1480 阅读 · 0 评论 -
【Java】异常处理 之 使用SLF4J 和 Logback
前面介绍了和Log4j这一对好基友,它们一个负责充当日志 API,一个负责实现日志底层,搭配使用非常便于开发。有的童鞋可能还听说过SLF4J和Logback。这两个东东看上去也像日志,它们又是啥?其实SLF4J类似,也是一个日志接口,而Logback类似于Log4j,是一个日志的实现。为什么有了和Log4j,又会蹦出来SLF4J和Logback?这是因为Java有着非常悠久的开源历史,不但OpenJDK本身是开源的,而且我们用到的第三方库,几乎全部都是开源的。原创 2023-08-10 09:43:53 · 293 阅读 · 0 评论 -
【Java】异常处理 之 使用Log4j
前面介绍了,可以作为“日志接口”来使用。而真正的“日志实现”可以使用Log4j。Log4j是一种非常流行的日志框架,最新版本是2.x。Log4j当我们使用Log4j输出一条日志时,Log4j自动通过不同的Appender把同一条日志输出到不同的目的地。在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。例如,仅输出ERROR级别的日志。最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。原创 2023-08-10 09:33:37 · 854 阅读 · 0 评论 -
【Java】异常处理 之 使用 JDK Logging
在编写程序的过程中,发现程序运行结果与预期不符,怎么办?当然是用打印出执行过程中的某些变量,观察每一步的结果与代码逻辑是否符合,然后有针对性地修改代码。代码改好了怎么办?当然是删除没有用的语句了。如果改代码又改出问题怎么办?再加上。反复这么搞几次,很快大家就发现使用S非常麻烦。怎么办?解决方法是使用日志。那什么是日志?日志就是Logging,它的目的是为了取代。输出日志,而不是用,有以下几个好处:可以设置输出样式,避免自己每次都写"ERROR: " + var;原创 2023-08-09 16:22:02 · 129 阅读 · 0 评论 -
【Java】Java核心类 之 常用工具类
实际上有多种不同的底层实现,有的使用安全随机种子加上伪随机数算法来产生安全的随机数,有的使用真正的随机数生成器。这两个类的区别在于,由于浮点数计算存在误差,不同的平台(例如x86和ARM)计算的结果可能不一致(指误差不同),因此,实际上真正的真随机数只能通过量子力学原理来获取,而我们想要的是一个不可预测的安全的随机数,实例时,如果不给定种子,就使用系统当前时间戳作为种子,因此每次运行时,种子不同,得到的伪随机数序列就不同。所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的。原创 2023-07-24 22:53:10 · 346 阅读 · 0 评论 -
【Java】Java核心类 之 BigDecimal
调用divideAndRemainder()方法时,返回的数组包含两个BigDecimal,分别是商和余数,其中商总是整数,余数不会大于除数。必须使用 compareTo() 方法来比较,它根据两个值的大小分别返回负数、正数和0,分别表示小于、大于和等于。如果一个BigDecimal的scale()返回负数,例如,-2,表示这个数是个整数,并且末尾有2个0。比较BigDecimal的值是否相等,必须使用compareTo()而不能使用equals()。比较 BigDecimal。原创 2023-07-24 18:20:34 · 231 阅读 · 0 评论 -
【Java】Java核心类 之 BigInteger
如果 BigInteger 表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用 intValueExact()、longValueExact()等方法,在转换时如果超出范围,将直接抛出ArithmeticException异常。使用longValueExact()方法时,如果超出了long型的范围,会抛出ArithmeticException。和 long 型整数运算比,BigInteger 不会有范围限制,但缺点是速度比较慢。原创 2023-07-24 16:52:31 · 170 阅读 · 0 评论 -
【Java】Java核心类 之 记录类
使用String、Integer等类型的时候,这些类型都是不变类,一个不变类具有以下特点:定义 class 时使用 final,无法派生子类;每个字段使用final,保证创建实例后无法修改任何字段。假设我们希望定义一个Point 类,有x、y两个变量,同时它是一个不变类,可以这么写:为了保证不变类的比较,还需要正确覆写equals()和hashCode()方法,这样才能在集合类中正常使用。后续我们会详细讲解正确覆写equals()和hashCode(),这里演示Point不变类的写法目的是,这些代码写原创 2023-07-24 16:25:58 · 122 阅读 · 0 评论 -
【Java】Java核心类 之 枚举类
在Java中,我们可以通过static final来定义常量。无论是int常量还是String常量,使用这些常量来表示一组枚举值的时候,有一个严重的问题就是,编译器无法检查每个值的合理性。上述代码编译和运行均不会报错,但存在两个问题:注意到Weekday定义的常量范围是0~6,并不包含7,编译器无法检查不在枚举中的int值;定义的常量仍可与其他变量比较,但其用途并非是枚举星期值。原创 2023-07-23 22:28:24 · 138 阅读 · 0 评论 -
【Java】Java核心类 之 JavaBean
在 Java 中,有很多class的定义都符合这样的规范:若干private实例字段;通过public方法来读写实例字段。原创 2023-07-20 13:50:17 · 73 阅读 · 0 评论 -
【Java】Java核心类 之 包装类型
我们已经知道,Java的数据类型分两种:基本类型:byte,short,int,long,boolean,float,double,char引用类型:所有 class 和 interface 类型那么,如何把一个基本类型视为对象(引用类型)?原创 2023-07-20 11:10:01 · 57 阅读 · 0 评论 -
【Java】Java核心类 之 StringJoiner
要高效拼接字符串,应该使用StringBuilder。慢着!用StringJoiner的结果少了前面的"Hello “和结尾的”!练习。原创 2023-07-19 14:31:51 · 213 阅读 · 0 评论 -
【Java】Java核心类 之 StringBuilder
Java编译器对 String 做了特殊处理,使得我们可以直接用+拼接字符串。虽然可以直接拼接字符串,但是,在循环中,每次循环都会创建新的字符串对象,然后扔掉旧的字符串。这样,绝大部分字符串都是临时对象,不但浪费内存,还会影响GC效率。如果我们查看StringBuilder的源码,可以发现,进行链式操作的关键是,定义的append()方法会返回this,这样,就可以不断调用自身的其他方法。仿照StringBuilder,我们也可以设计支持链式操作的类。原创 2023-07-19 14:25:20 · 425 阅读 · 0 评论 -
【Java】Java核心类 之 字符串和编码
因为英文字符的Unicode编码高字节总是00,包含大量英文的文本会浪费空间,所以,出现了UTF-8编码,它是一种变长编码,用来把固定长度的Unicode编码变成1~4字节的变长编码。例如,字符’A’的编码是0x41,字符’1’的编码是0x31。这是因为通过new String(char[])创建新的String实例时,它并不会直接引用传入的char[]数组,而是会复制一份,所以,修改外部的char[]数组不会影响String实例内部的char[]数组,因为这是两个不同的数组。原创 2023-07-19 13:27:46 · 274 阅读 · 0 评论 -
【Java】面向对象基础 之 模块
我们知道,.class 文件是 JVM 看到的最小可执行文件,而一个大型程序需要编写很多Class,并生成一堆.class文件,很不便于管理,所以,jar文件就是 class 文件的容器。在Java 9之前,一个大型Java程序会生成自己的jar文件,同时引用依赖的第三方jar文件,而JVM自带的Java标准库,实际上也是以jar文件形式存放的,这个文件叫rt.jar,一共有60多M。注意:JVM自带的标准库rt.jar不要写到classpath中,写了反而会干扰JVM的正常运行。原创 2023-07-18 22:38:28 · 398 阅读 · 0 评论