type
Post
status
Published
date
Feb 5, 2025
summary
tags
开发
slug
ex
category
Java学习笔记
icon
password
😀
自学Java笔记
 

📝 Java 基础学习笔记

 

Java基础语法

Java主类结构

关键字class定义对象类型
如果要是这个类成为一个能够独立运行的程序,这个类必须包含一个名为main()的方法,此时这个类也被称为主类。一个类只能有一个主方法,但是可以定义多个方法。
命名主类名称时,需注意大小写,第一个字母须大写,同时主类名称要与文件名称保持一致。

java包

  • package关键字
包的声明应该在第一行,而且每个Java文件只能有一个包声明。 包名以小写命名,不可用数字开头。
package java 文件名
  • import关键字
引入特定包的内容。import关键字声明后面段落为引入的具体内容。指定某个类文件则写明具体的类文件名,也可以不指定具体的类名,使用“”来指定这包
下面的所有类文件。 import声明必须在package包声明之后,类声明之前。 类的全局变量与局部变量 全局变量是指类中直接声明的属性,能够在类中各个地方调用。 局部变量是指在方法中声明的属性,局部变量只能在声明的方法中使用。 访问权限修饰词public、private、protected 包访问权限 当不写以上三种修饰词时,java会默认该类的访问权限为包访问权限,即这个包下的其他类文件都可以访问该类 公开访问权限 用pubilc标识的该类或者成员变量、函数对其他所有类文件都是开放的的,其他类文件都可以直接进行调用,调用时只需用import关键字引入即可。 私有访问权限 用private标识的成员变量,成员函数只可以在自己的类文件内使用,其他任何类文件都无法访问和使用这个变量或函数 继承访问权限 用protected标识的变量,可以在该变量所在类的所有子类内使用,也可以在该变量所在的包内的其他类内使用。 编写主方法 每个java应用程序都必须有且仅有一个main()主方法,main()主方法必须被声明为pubilc static void,并且入参必须是String[]arg或者String args[]。 每个java程序在运行时都要创建一个java虚拟机(java Virtual Machine 简称JVM)实例,由JVM从外部调用main()方法就需要公开访问权限,所以main()必须要用public声明。 void表示main()方法没有具体返回值 static关键字可以修饰类的属性和方法,被static修饰的成员被称作“静态成员”。静态成员不会创建对象,只会作为类的共享属性进行管理,所有使用了静态成员的地方都共享同一个静态成员。 String[]args是主方法的参数列表,是一个数组类型的参数。 注释及使用场景

基本数据类型

  • 整数类型
byte类型占用内存8位,一个字节,用二进制补码表示整数(-2^7~2^7-1)默认值为0 short类型占用内存16位,两个字节,用二进制补码表示整数(-2^15~2^15-1)默认值为0 int类型占用内存32位,四个字节,用二进制补码表示整数(-2^31~2^31-1)默认值为0 long类型占用内存64位,八个字节,用二进制补码表示整数(-2^63~2^63-1)默认值为0L。
  • 浮点类型
默认为double类型 float类型占用内存32位,四个字节,默认值为0.0F。 double类型占用内存64位,八个字节,默认值为0.0D。 浮点数的进度有限,永安不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。在财务系统,一般会在Java中使用BigDecimal类开计算财务报表。
  • 字符类型
char类型是一个单一的16为Unicode字符,使用单引号('')表示字符。(0~65535)默认值是' ' char类型可以当整数来用,它的每一个字符都对应一个数字。 布尔类型 boolean占用内存8位,一个字节,它只有false与true两个值,默认值为false。
  • 引用类型对象 对象的类型也被称为“引用类型”,因为对象的赋值和使用都是通过引用底层固定内存地址进行的。 特殊值null 他表示一个变量没有任何值。null可以认为是任何引用类型的默认值。 null既不是对象,也不是基本数据类型,它只是一个特殊值,并且可以赋值给任何引用类型对象。 数据类型之间的转换 自动转换(低精度到高精度转换)
  • 强制转换(高位数的数据类型向低位数的数据类型转换)

变量与常量

常量命名一般由大写字母+下划线组成 变量的命名 区分大小写 有字母下划线,数字或者美元符号构成 数字不可以放在第一位 不可以使用java关键字
java属于强类型语言,在声明变量时需要明确变量的声明类型。

操作运算符

算术运算符 比较运算符 赋值运算符 递增、递减运算符 逻辑运算符 三元运算符 位运算符 instanceof运算符 特殊运算符,用于检查一个对象是否由指定类定义的。这里的类包括抽象类、接口等。 运算符优先级

表达式

表达式是Java中最重要、最基础的组成元素。java中,绝大部分代码都是表达式。 任何有值的东西都可以被称作表达式。
Java方法
方法定义和使用 [修饰符][返回类型]方法名([参数类型]参数名...){ //方法体执行语句 } 方法名为必填项,命名规则和java中的其他标识符相同,有效的方法名以字母或者下划线开头后面跟字母、数字和下划线。方法名应该能够反映方法所执行的任务,一般以小写字母开头定义规范。 java中提供了main()方法,编译后程序会优先从main()方法开始执行。 java定义的方法不能独立出现,必须定义在类中。通过名称调用的方式也只能在该类中调用,其他类中要调用该类的方法,就需要指明调用方法是在哪个类中。调用方式为“类名.方法” 方法参数 方法返回值 ,

Java流程控制和语言结构

条件控制语句 if switch 循环控制语句 for循环语句 foreach循环语句 for([类型]变量:遍历对象){ //循环体中执行语句 } while do...while循环语句 跳转语句 continue语句 break语句 return语句

字符串

  • 字符串String类
String类是final类,在java中,被final修饰的类是不允许被继承的,并且String类中的成员方法都是默认为final方法。String类实际上是通过char字符数组来保存字符串的。 创建字符串 字符串是常量,可以储存任意长度的字符信息,被创建后其值不能被更改,长度也不能被改变。java中可以通过String类创建保存字符串的变量,也就是对象。虽然表面上可以给String类定义的变量进行赋值运算,但实际是创建了一个新的String对象并指向定义的字符串常量。然后将这个对象的内存地址引用赋值给了该变量。原来创建的String对象没有改变,它和新创建的对象虽然内容相同,但是在系统中的内存储存空间并不同一个, 这两个对象在面向对象编程中会被认为两个不同的对象。 初始化字符串 1.直接通过字符串常量赋值 2.构造方法初始化 使用构造方法初始化字符串对象和直接引用赋值类似,但是它们背后的逻辑并不相同。 使用构造方法new String(“字符串”),实际上创建了两个String对象,一个是字符串常量,储存在常量池中,一个是用new关键字为对象申请空间。 3.基本数据类型转换方法 String类中提供所有基本数类型的valueOf()方法,可以将基本数据类型转换为字符串,并且这些方法都是静态的。直接可以通过“String。valueOf()”方式直接调用。 java中不可以将(String)置于待转换的变量前并将其强制转换为字符串,因为String是对象类,并不是基本数据类型。 字符数组初始化 String类中提供了方法,可以使用一个字符数组初始化一个字符串,也可以使用字符数组中的一部分内容初始化一个字符串。 字符串的常见操作 字符串连接 使用“+”运算符来连接多个字符串。当创建一个新的字符串时,“+”运算符的两边必须都是字符串或者String对象。 String类还提供concat(String str)方法,可以将入参str字符串对象拼接到指定对象的后面。若入参str变量为空,会直接返回制定对象。否则concat()方法返回的都是新创建的对象,并不会改变原来对象的内容。 字符串长度 length(),返回值为整型(返回的是UTF-16编码下的个数,不论是数字、字母、符号、空格、汉字,每个字符的长度都是1)。 String类实际是使用字符数组来储存字符串的,所以当调用length()方法时,实际是直接获取存储字符数组的长度 查找字符串 1.charAt()方法 2.indexOf()方法 3.lastIndexOf()方法 字符串替换 String类中提供了两个同名replace()方法,一个入参为两个单一字符,另一个入参为两个CharSequence接口类。
CharBuffer、Segment、String、StringBuffer、StringBuilder都实现了CharSequence接口 replaceAll()方法 replaceFirst()方法 字符串截取 String类中提供了两个同名substring()方法,用来返回指定String对象中的子字符串,当只有一个入参时,是从入参位置开始截取直至结尾。当有两个入参时,是从开始索引位置截取到指定结束索引-1的位置.(相当于左闭右开的区间取值范围) 字符串分割 String类中提供了两个同名split()方法,用来将一个字符串按照一定规则分割成字符串数组。当只有一个入参时,通过与入参比较,将入参两侧分割。当有两个入参时,可以根据入参分割符对指定String对象进行有限次的分割。 字符串首尾内容判断 startsWith()和endsWith(),两个方法的返回值都是boolean类型 字符串首尾去空格 String类中trim()方法可以返回一个去除首尾空格的字符串 字符串大小写转换 toLowerCase()方法可以将指定对象中每个字符都转换为小写字母,字符长度保持不变。 toUpperCase()方法可以将指定对象中每个字符都转换为大写字母,字符长度保持不变。 因为ASCII码中,大写字母比小写字母要小32个数值,所以可以使用字母的ASCII编码偏移的方式 来实现字符串大小写的转换。 字符串比较 对String对象来说,双等号比较的是两个对象的引用内存地址是否相同。String类中提供了equals()和equalsIgnoreCase()两个方法来比较字符串对象的内容是否一样,若被比较的参数为null,则会返回false。 比较时,equals()区分大小写,equalsIgnoreCase()不区分大小写。 字符串格式化输出 format()方法用来创建格式化后打字符串对象。format()方法只能通过“String.format”静态方法进行调用,不能直接使用对象来调用。 format(String format, Object...args) java中字符串支持的转换符 其他字符串操作 contains(CharSequense s) 判断指定String对象中是否包含入参字符串,返回布尔值。 compareTo(String anotherString) 按字母排序比较两个字符串,返回整型。该方法会先按照ASCII码比较对应字符大小,如果第一个字符和参数的第一个字符不等,结束比较,返回它们之间打差值,若相等,继续比较第二个字符,以此类推,直到不相等返回。若从头到尾都相等,返回0,若指定String对象的字符串小于字符串入参时,返回一个小于0的值,反之则返回一个大于0的值。 compareToIgnoreCase()忽略大小写 hashCode() 返回该字符串的哈希值,若指定字符串为空,则返回0。 toCharArray() 将字符串转换成一个新的字符数组 toString() 不是String类特有,它也是Object类中的方法。可以通过重写toString()方法来提供自己想要的字符串格式。
  • StringBuilder类和StringBuffer类
操作字符串时并不生成新的对象,而是直接操作原来生成的内容,这在内存上要优于String。 StringBuilder和StringBuffer的方法基本一致,不同的是Stringbuilder是非线程安全的,StringBuffer是线程安全的,但是Stringbuilder的效率比StringBuffer的高。 StringBuilder类 1.创建StringBuilder对象 StringBuilder类需要通过new关键字来创建一个新对象,不能直接通过“=”将字符串常量赋值给StringBuilder的对象。StringBuilder类有四种构造方法初始化StringBuilder对象。
StringBuilder默认创建的是一个容量16字符的对象,超出时会扩容,也可以通过构造器创建一个指定容量的对象。 2.append()方法 将基本类型数值和字符数组转换为字符串,并将其添加到StringBuilder对象的末端。 3.insert()方法 将基本类型数值和字符数组转换为字符串,插入到StringBuilder对象指定入参索引位置处,其他字符位置依次向后移。 所谓插入到指定索引位置,是指插入的第一个字符的位置。 4.delete()方法 删除该对象指定索引范围的字符内容 delete(int start,int end) 若end大于StringBuilder对象的最大长度,会直接更正为最大长度。 5.charAt()方法 该方法会返回在StringBuilder对象序列中的入参索引位置的字符值。 6.capacity()方法 该方法返回当前容量,以字符为单位。 7.replace() StringBuilder类的replace()方法可以将整个字符串序列中指定范围内的字符序列统一替换成新的入参字符串。 replace(int start,int end,String str) 8.reverse()方法 将字符串序列反转,创建一个新的StringBuilder对象。 9.toString()方法 StringBuilder重载的toString()方法实际上是利用String类中的构造方法new String(value,0,count)来创建一个新的String对象。而System.out.println()方法的入参可以直接是StringBuilder类对象,这在源码中也可以找到原因--println()方法的源码中使用了String.valueOf(Object o)方法,将StringBuilder对象转成字符串。
  • StringBuffer类
方法基本与StringBuilder类一样。

数组

数组可以是视为一种基础引用类型,并不像集合类一样可以使用迭代器,不能使用Java中的泛型。 数组创建 数组创建方法 创建数组时,需要指定数组长度,系统会自动分配内存;没有分配内存空间的数组(只定义了数组类型,没有定义数组内容)无法被访问。 [数组类型] 数组名[]; [数组类型][]数组名; 数组初始化有几种方法:直接将数组内容赋值给数组变量、使用new创建数组内容、使用new先创建数组,再给数组内容赋值。无论哪种方式,数组一旦创建,其长度就不能被更改。数组和对象类似,都是引用赋值。 数组索引 数组通过方括号内的数字访问内部元素的,这个数字被称为下标或者索引。数字索引默认是从0开始线性自增。访问数组中单独位置的元素也可以直接通过数组索引来进行。 多维数组 数组类型 数组[][]=new 方法名[][]{{第一个数组},{第二个数组}} 多维数组的含义就是,数组中的每个元素也是一个数组,且这些子数组中的每个元素依旧可以是一个数组。二维数组可以是一个有行有列的表格,三维数组可以当做一个立方矩阵。 多维数组在java中分配的储存空间并不是连续的,所以创建多维数组时可以只定义第一个方括号内的长度而忽略其他多维的长度定义,其他维度的长度可以分别定义。但是第一个数组的长度不可省略。 数组虽然处理速度快,但是也存在一些问题,因为数组都是静态的,定义时需要考虑容量大小,一旦定义好,便不能更改,而在实际开发中并不能预制容量大小。一般情况下,会使用Java中的集合类,如List类和Map类等,来支持更为复杂的多维结构。 数组的遍历和输出
 
Arrays类中的toString静态方法
java.util包提供了Arrays类以专门处理数组的排序和遍历。Arrays.toString静态方法可以用来遍历输出指定的数组内容。Arrays中的方法都是静态的,需要通过“Arrays.toString()”直接调用类名的方式来进行调用。 对于多维数组,静态方法Arrays.toString并不能直接使用,需要使用deepToString静态方法才能输出多维数组内的所有元素。 数组常见操作 数组长度 数组对下标 自带length属性,数组初始化后length属性会保存数组的长度。多维数组同样有length属性。 数组添加元素 Arrays类中提供了可以给数组批量添加相同元素的静态方法fill(),调用时入参为被添加元素的数组和要添加的值。fill()方法支持Java中所有的基本类型和引用类型。fill()方法也可以指定数组要添加的索引范围(左闭右开区间),入参为起始索引和终点索引。 数组创建后不能修改长度,但是我们可以在数组中的特定位置添加元素,再生成一个新数组。原数组不变。 注:数组创建后不能修改长度,但是我们可以在数组中的特定位置添加一个新数组,为元素组扩容。扩容后,原数组长度不变,取元素,须按多维数组的方法。 删除数组元素 数组长度不能更改,但是可以通过新建一个删除元素后的新数组的方法,达到删除数组指定元素的目的。 删除重复数据 Java中的集合类有提供方法或者不重复Set类支持一去掉一个集合数据中的重复数据,但是针对数组则没有现成的方法。因为数组的长度是固定的,所以使用前必须初始化长度。系统提供了System.arraycopy()方法来直接复制数组特定范围的内容并创建一个新数组,其去重的思想则是利用两层嵌套循环,将数组元素依次比对后再将不重复的元素存入一个新的数组中,并使用一个计数变量将实际数组长度记录下来,这样就达到了删除重复数据的目的。 数组查找 数组查找就是查询一个数组内是否存在某个元素。可以通过for循环来遍历数组。 Arrays类提供了binarySearch()方法,能够找到指定元素的在数组中的位置,这方法支持多种基本类型和引用类型数组入参。若无法找到返回-1。 binarySearch()采用二分法,其思想是:假设数组中的元素按照升序排列,现将数组中间位置的元素与要查找的元素比较,若相等则直接返回,若不相等,将原数组分为两个数组,,若中间元素大于待查元素,就在前面的子数组内重复上述步骤,反之,则相反。 一般在使用binarySearch()方法前,需要先调用Sort()方法对数组进行排序。 数组排序 Arrays类中自带排序方法,可以将数组进行升序排序。 Arrays.sort(要排序的数组名) Arrays。sort()方法采用的是双轴快速排序,除此之外还有常用的冒泡希尔排序、选择排序、堆排序、快速排序、归并排序。桶排序等。 数组复制 System.arraycopy()方法是一种复制数组的底层实现方法。Arrays类中提供了数组复制的方法copyof(),其入参除了要复制的数组外,还要提供复制后的数组长度。如果复制后的数组长度与原来相等,则会返回一个与原来数组内容一样的新数组;如果长度大于原来数组的长度,则会填充数组类型的默认值。若长度小于原来数组的长度,则会从原来数组的索引0处开始截取相应长度的数组内容。 数组比较 Arrays类中提供了重载后的equals()方法,用来比较两个数组的内容是否相同。

正则表达式(Regular Expression)

符合一定规则的表达式,就是用于匹配字符中字符组合的模式。 正则表达式语法 普通字符 中括号”[ ]“表示这个是一个字符组。代表一个字符,"-"表示连续的区间范围 [0-9]、[A-Za-z] 当允许的字符范围只有一个时,则可以省略“[ ]” [ \[ ]
字符转义 在正则表达式中有一些字符有在特殊含义,不能代表字符本身,此时在字符前加上“\”,才能代表其本身。
元字符 在正则表达式中有特殊意义的字符,被称为元字符 常见的元字符如下:
限定符 限定父指定在输入字符串中必须存在上一个元素的多少个实例才能找到匹配项。 {n}限定符表示匹配上一元素n次,其中n是任何非负整数。 {n,}限定符表示至少匹配上一元素n次,其中n是任何非负整数。 {n,m}限定符表示至少匹配上一个元素n次,但不超过m次,其中n和m是非负整数。 *限定符表示与前面的元素匹配零次或者多次,它相当于限定符{0,} +限定符表示匹配上一元素一次或多次,它相当于限定符{1,} ?限定符表示匹配上一元素零次或一次,它相当于限定符{0,1} 定位符 定位符能够将正则表达式固定到行首或行尾,还能创建一些在一个单词内、一个单词的开头或者一个单词的结尾出现的正则表达式。 定位符用来描述字符串或单词的边界。"^"和"$"分别指字符串的开始与结束,"\b"描述单词的前或后边界,“\B”表示非单词边界。 正则表达式中常见的定位符 "^"定位符指定以下模式必须从字符串的第一个字符位置开始 "$"定位符指定前面的模式必须出现在输入字符串的末尾,或出现在输入字符串末尾的"\n"之前。 "\b"定位符指定匹配必须出现在单词字符("\w"语言元素)和非单词字符("\W"语言元素)之间的边界上单词字符包括字母、数字字符和下滑线;非单词字符包括不是字母、数字字符或下划线的任何字符。匹配也可以出现在字符串开头或结尾处的单词边界上。"\b"定位符经常用于确保子表达式与整个单词匹配,而不仅仅与单词的开头或结尾匹配。 "\B"定位符指定匹配不得出现在单词边界上,它与"\b"定位符正好相反。 分组构造 分组构造描述了正则表达式的子表达式,用于捕获输入字符串的子字符串。可以使用"()"(英文小括号)分组构造捕获匹配的子表达式: (子表达式) 子表达式为任何有效正则表达式模式。使用括号的匹配捕获按正则表达式中左括号的顺序从一开始就从左到右自动编号 匹配模式 匹配模式指的是匹配时使用的规则。使用不同的匹配模式可能会改变正则表达式的识别,也可能会改变正则表达式中字符的匹配规定 不区分大小写模式,指的是在匹配单词时,正则表达式将不会区分字符串中字母的大小写。 单行模式(或者叫点号通配)会改变元字符"."的匹配方式。 多行模式改变的时"^"和"$"的匹配方式 java处理正则 java util.regex包介绍 从JDK1.4开始,JDK提供了支持正则表达式的java.util.regex包,其中提供了两个类--Pattern类和Matcher类。 Java的正则表达式中的许多元字符都是使用反斜线"\"开头,这与Java在字符串相同的字符使用产生冲突。如想要匹配文字"\”,那么正则表达式应该写成“\\\”来匹配字符串。 Pattern类 Pattern类与Perl正则表达式类似,其正则表达式和要搜索的字符串以Unicode字符串(String)形式出现。Pattern对象就代表一个正则表达式,也可以认为时一个匹配模式。 由于Pattern的构造方法时私有的,没有公有的构造方法,不可以直接创建,需要通过方法complie(String regex)和指定正则表达式来创建一个Pattern对象。 Pattern类常见方法 Pattern类总是和Matcher类同时使用,对匹配正则表达式的内容进行操作。 Matcher类 Matcher类使用Pattern对象提供的匹配信息对正则表达式进行匹配。Matcher类与Pattern类一样,位于java.util.regex包中。Matcher类中最常用的三个方法为matches()、lookingAt()和find()。其中,matches()方法用于对整个目标字符串进行检测判断;lookingAt()方法用于对前面的字符串进行匹配,只有匹配到的字符串在最前面时才返回true;find()方法用于对字符串进行匹配,匹配到的字符串可以出现在任何位置。 Matcher类常见方法 当一个字符串中有多个字符组合满足正则表达式时,就可以使用Matcher对象的分组功能,对每个组合进行操作。 PatternSyntaxException类 PatternSyntaxException类是一个非强制行性的异常类,在正则表达式出现语法错误时系统会抛出该类异常 知识拓展 贪婪与非贪婪匹配 贪婪匹配是指限定符尽可能多地匹配字符串;默认情况下,限定符都是贪婪匹配。非贪婪匹配则是指定限定符尽可能少地匹配字符串;一般情况下,在限定符后加上“?”表示非贪婪匹配 零宽断言 零宽断言是一种零宽度的匹配。它匹配的内容不会保存到匹配结果中,因为表达式的匹配内容只是代表一个位置而已。 常用断言字符
常用正则表达式参考

面向对象编程

面向对象的介绍 java与面向对象 类的声明 [访问权限修饰词] [修饰符] class [类名]{ 成员属性声明; 成员方法 } 类的实例化 Job job//job=null,如果想使用该对象,需要使用java中的关键字new来创建一个对象并分配 Job job=new Job();// java中创建对象实际是将对象的内存地址传给了变量,这也被称为引用。 当一个对象被使用结束后,他就会被处理为垃圾;JVM的垃圾回收机制(GC)会将这个对象销毁,这个对象也将不能被使用,此时引用这个对象的地址将会指向null。 成员属性 [访问权限修饰符] [修饰符][数据类型] [变量名] 成员方法 [访问权限修饰词] [修饰符] [返回数据类型][方法名](参数列表){ [方法体] } 方法名命名规范一般是“动词+名字”的驼峰形式,方法名的第一个单词小写,后面的单词首字母大写。 访问成员的属性和方法 创建一个对象后,成员的属性和对象就可以访问,通常使用“引用.属性/方法”的调用方式来获取这个对象的属性或方法。 Java中另外提供了高级编程方式——反射,在知道成员属性和方法名称的时候,可以直接获取及调用成员属性和成员方法。 变量作用域 类级变量作用域 类级变量是指类中的全局变量或静态变量,用static修饰。类级变量在类定义后会在内存中单独分配一块储存空间,可以直接通过类名访问,但不能通过实例化的对象来访问。类级变量作用域位于这个类内的任何地方,也就是说该类的任何地方都可以使用声明的类级变量。 对象成员变量作用域 对象实例化后成员变量可以被类中的任意代码访问,如果是非私有的变量,也可以被其他类的代码访问。如果一个对象没有被实例化,则它的成员变量不能被其他类的代码访问。 方法级变量和代码块变量作用域 在成员方法和代码块中定义的变量称为局部变量,这里的代码块是指流程控制语句内部、static定义的静态代码块等。局部变量在方法或代码块內执行时被创建,在方法或代码块结束时被销毁。局部变量在使用前必须通过初始化或赋值运算,否则编译时会报错。
对象的应用 对象比较 值类型比较和引用类型比较 值类型比较是指两个对象的值是否相等,如果两个对象的内容相同,则认为它们的值是相等的。java中会使用类中的equals()方法来比较两个对象的内容是否相等。引用类型比较,是指两个对象在内存空间的储存地址是否相同。引用类型比较直接使用运算符“==”来进行比较。 JVM这样处理String也是因为String类型所创建的对象具有不可变性,一般被创建,就永远不能被更改,所以多个引用共用一个对象也不会互相影响。 对象销毁 Java中,当出现一下两种情况时,垃圾回收机制会将一个对象销毁: 1)对该对象的引用超过饿了作用于,如在循环代码块里声明了一个对象,当循环代码结束时,该对象也会被销毁。 2)该对象被赋值为null。 Java垃圾回收机制也有特殊情况。如果对象(并没有使用new创建)获得了一块特殊的内存空间,由于垃圾回收机制只会释放有new关键字分配对象的内存,这种对象不会被销毁,也就是说对象并不是完全都会被垃圾回收。 修饰符关键字 static和final,它们可以作为变量、方法或者类的修饰符。 static是静态修饰符,可以用来修饰变量、方法或代码块。static修饰的变量被称为静态变量,static修饰的方法被称为静态方法。静态方法中不能调用非静态方法,但非静态方法可以调用静态方法。被static修饰的属性或方法对于每个类来说只有一份内存存储空间,没有被static修饰的是每个新创建的对象都会有一块对应的内存空间。 final是不可变修饰符,可以用来修饰变量、方法和类。在面向对象编程中,final用来定义“不可改变、不能更改”的数据。 静态常量 被static和final同时修饰的成员属性称为静态常量。在程序执行时,系统会先单独给这个常量分配一个不可变的内存空间,这样该常量就可以一直被使用,避免了内存资源的浪费。静态常量被创建后其值不能被更改。 静态变量 被static修饰的成员属性称为静态变量。在类加载时,静态变量最先被分配内存空间,同一个类的不同对象共享同一个静态变量。 静态方法 被static修饰的成员方法称为静态方法。同静态变量一样,静态方法也是在程序在最开始时被分配一块单独的内存空间,静态方法,是被共享的,可以直接通过“类名.方法名”方式调用,也可以直接实例化对选哪个,通过“对象.方法名”方式调用。静态方法中不能调用非静态方法,但是非静态方法也可以调用静态方法。 因为静态方法在执行是不一定存在该类的对象,所以静态方法内部不允许使用this关键字。 静态代码块 被static修饰的代码块被称为静态代码块,这是一种存在于类中、成员方法外的静态代码块,其中包括一系列可以执行的语句。静态代码块在类第一次被使用执行时,自始至终只会执行一次,往往用来初始化静态变量。 静态代码块中能在类里定义,不能在方法里定义。在类被加载时,静态代码块是最先被调用的。类定义的非静态代码块会在每次对象实例化是都被执行一次。 构造方法 类有一种特殊的成员方法叫做构造方法,他的作用是创建对象并初始化成员变量。构造方法与类同名,在创建类的对象时,会自动调用类的构造方法。构造方法没有返回类型,更不能定义为void。另外,构造方法一般应用public类型来说明,这样才能在程序的任意位置创建类的实例化对象。 每个类至少有一个构造方法,如果没有定义,Java会在编译时自动添加一个默认的构造方法,该构造方法没有参数,方法体也是空的;如果自定义了构造方法,则默认的构造方法在编译时不会被添加。 类的继承和多态 面向对象编程的三大特性:封装性、继承性、多态性。 继承 继承的基本思想就是在一个类的基础上,制定出一个新的类,这个新的类不仅可以继承原来类的属性和方法,也可以增加新的属性和方法。原本的类被称为父类,新的类被称为子类。 extends关键字类声明一个子类继承了父类,extends关键字后面只允许出现一个类名。子类可以继承父类所有的非私有的成员属性和方法。 一个子类只能有一个父类,但是一个子类可以有多个接口 子类可以定义与父类属性名相同的属性和方法,这是子类属性将覆盖父类的属性,这个过程被称为重写(Override)。 子类也可以重写父类的方法,此时子类重写的方法名称须与父类方法名称一致,切返回值类型和入参都不能改变,同时子类重写的方法不能缩小父类方法的访问权限。重写方法的好处在于,子类可以根据需要定义属于自己的行为。 成员方法定义是,会有抛出异常的情况。子类重写这类方法是必须和父类方法抛出异常保持一致, 子类不能继承父类的构造方法,父类的构造方法只属于父类。但是可以通过super关键字去访问父类的构造方法并给父类的成员属性进行赋值。调用父类的构造方法时,super语句必须是代码块的第一条执行语句。 this关键字可以用来获取子类中定义的成员属性或成员方法;当成员变量与方法内定义的变量重名时,也可以用this关键字来作区分并获取类中定义的成员变量。 子类在创建一个新对象时,执行顺序是先找到最根的父类,接着开始执行根父类的构造方法,然后依次向下执行派生出现饿的子类的构造方法,直到执行完所有子类的构造方法为止。 当创建一个类时,若没有指定父类,Java会默认使用该类继承Object类。也就是说,所有类都是Objec类的子类,都可以继承或重写Object类的方法。Object类中较常用的方法有equals()toString()、clone()。 多态 多态是指一个对象的行为可以有多种不同的表现形式。java中提供了重载(Overload),是构造方法可以有多种被调用的方式。重载是指在一个类里的方法名称相同,但是入参不同(可以是个数不同,也可以是类型不同,或者顺序不同),返回类型也可以不同。每个重载方法的调用是通过参数类型和参数个数来作区分的。 当方法只有返回值类型不同时,是无法区分是哪个方法的,所以代码中不允许这种情况发生。 在面向对象编程中,因为子类与父类存在继承关系,所以对象类型存在着转换,包括向上类型转换和向下类型转换。向上类型转换是指将子类对象引用转换为父类对象引用。子类对象也可以被当做父类的对象。这是因为继承的关系,子类总能包含父类的非私有成员。一般情况下,变量会被声明为父类的类型,引用子类的对象。但向上类型转换后,声明的父类无法调用只在子类中定义的成员,因为父类中并没有这些信息。 向下类型转换与向上类型转换动作相反,是指将父类对象引用转换为子类对象引用。这种转换通常会出现问题。因为很明显子类中的内容可能并不存在与父类中,如果直接将父类对象引用赋值为子类定义的变量,程序会变编译失败,即父类的对象并不一定是子类的对象。因此,向下类型转换总是伴随着向上类型转换一起出现的。 Java中提供instanceof关键字来判断一个对象是否是一个类的实例。同时也可以判断一个类是否实现了某个接口。 [对象名]instanceof[类名]//返回值为布尔值 向上类型转换的对象即是父类的实例化对象,也是子类的实例化对象。如果一个类和另一个类不存在继承关系,使用instanceof进行判断时编译器会报错。 高级特性 final的使用 final关键字标识的属性或方法在程序中“不想被改变”,它会告知编译器这一部分数据是不可变更的。 final修饰类 不能被继承。这种设计方法是为了保证该类的设计永远不需要做任何改动,而且不希望该类有子类出现。 由于final类禁止被继承,不会出现覆盖方法的情况,所以final类中所有的成员方法都被隐式定义为final。但是final类中是允许成员变量不被定义为final的。 final修饰变量 被final修饰的变量,一旦被初始化就不能被更改,一般用作常量。被final修饰的变量在声明时必须被赋值,可以在变量定义时直接赋值,也可以在构造方法中赋值,但两者必须二选一。final定义的变量不仅可以修饰基本数据类型,也可以修饰对象。 final修饰方法 被final修饰的方法不允许被覆盖重写,这是为了保证子类不能随意更改父类中定义的方法。但是,被final修饰的非私有方法,仍可以被子类继承,可以通过子类来访问父类的final非私有方法。 final修饰方法入参 final可以修饰方法的入参,被修饰的入参表示在整个方法的代码块中,参数无论是基本数据类型还是对象引用数据类型,都无法被重新赋值(入参传入进来就相当于变量的初始化完成)。给方法入参添加final是一种代码风格保护机制,以避免在大段的代码块中误操作和错误改写变量值。 对象克隆 浅克隆 如果待克隆对象的成员属性是基础值类型,将赋值一份给克隆对象; 如果待克隆对象的成员属性是引用类型,则将该引用对象的地址复制一份给克隆对象,也就是说待克隆对象和克隆对象的成员属性都会指向相同的引用内存地址。 浅克隆的实现方法为:先是类实现Cloneable接口,然后重写Object.clone()方法。 深克隆 在深克隆中,无论是待克隆独享的成员属性都是基础值类型还是引用类型,都将赋值一份给克隆对象,所有引用对象也都会重新克隆一份过去。 如果对象的成员属性为引用类型,而这个类型中还包含很多引用类型,或者内层有嵌套包含引用类型,使用clone()方法将会很麻烦。 Java中提供了序列化的方式来实现对象的深克隆,而要实现序列化对象的类则必须实现Serializable接口。 序列化是将对象转换成流的过程,通过序列化不仅可以复制对象本身,也可以复制其成员属性引用的对象。

抽象类与接口

Java语言中提供了抽象类和接口,这是一种将接口和实现分离的结构化编程思想,能使代码保持整洁,便于维护。 抽象类 用abstract关键字来定义一个抽象类或抽象方法。 [访问权限修饰符]abstract class[类名] 抽象类一般被设计出来作为最基础的类,包含一些通用的基本成员属性和成员方法。在抽象类中甚至可以只给出方法的定义而不实现,具体实现由继承的子类来完成,这些方法也被称为抽象方法。抽象类不能用来实例化,所以抽象类的构造方法是不能定义为抽象方法的,它的子类也必须重写该类的所有抽象方法。 如果继承抽象类的子类也是抽象类,该子类可以不实现父类中的所有抽象方法。但是该抽象子类的实现类必须实现抽象父类与子类的所有抽象方法。 抽象类中的方法可以有具体实现,也可以没有具体实现而成为抽象方法。含有抽象方法的类必须被定义为抽象类。 接口 接口是一种更为抽象的类,其定义的方法不允许实现方法(没有方法体,只是定义了方法入参,方法名和返回值类型),没有任何与接口相关的储存。接口的子类也不称为继承,而是称为实现类。 Java用interface关键字来定义一个接口类。用implements关键字来实现接口,同时这个类需要实现接口内所有的方法。 接口支持多重继承,一个类可以同时实现多个接口。 [访问权限修饰符]interface[类名] 接口只可以定义常量和抽象方法。接口对外定义了输入、输出格式,而将内部的具体实现隐藏起来。 知识拓展 单例设计模式

Java常用类

包装类 java在java.lang包中提供了八种基本数据类型对应的包装类,可以很方便地将他们转换为对象进行处理,并且可调用一些方法。 Byte、Short、Integer、Long、Float、Double都是抽象类Number的子类,同时Number的子类必须提供将数值转换为基本类型byte、short、int、long、float、double的方法。 从JDK1.5开始,引入了自动拆箱和自动装箱的概念。装箱是指将基本类型的值转换为包装类对象,拆箱是指将包装类对象转换成基本类型的值。 一个对象没有初始化或者null,自动拆箱过程中会抛出NullPointerException异常;Java会对-128至127的整数进行缓存,直接自动装箱同一个int基本类型值的不同对象,在用“==”比较时,会返回true,但是明显这两个对象不相等;有时自动装箱会隐蔽地创建对象。 Integer整型类 Integer类中的常量 Integer类构造方法 Integer(int number)//以整型数值为入参创建一个Integer对象 Integer(String str)//以String字符串为入参创建一个Integer对象 Integer类中的常用方法 Double浮点型类 Float类与Double类相似,都是Number类的子类,所包含的方法基本相同,唯一不同的的,Float封装的数据类型为float单精度浮点类型,Double封装的数据类型为double双精度浮点类型。 Double类中的常量 Double类构造方法 Double类提供两种构造方法 1)Double(double number) 以double浮点型数值为入参创建一个Double对象 2)Double(String str) 以String字符串为入参创建一个Double对象 Double类中的常用方法
Boolean布尔型类 Boolean类是boolean基本类型的包装类,它包含一个类型为boolean的字段。 Boolean类中的常量 Boolean类构造方法 Boolean类提供两种构造方法 1)Boolean(Boolean value) 以Boolean布尔数值为入参创建一个Boolean对象 2)Boolean(String str) 以String字符串为入参创建一个Boolean对象 Boolean类中的常用方法 Character字符型类 Character类中的常量 Character类构造方法 Character类只提供一种构造方法 Character(char value) 以char字符数值为入参创建一个Character对象 Character类中的常用方法 高精度数字 Java中的java.math包提供了两个高精度的数字类BigInterger和BigDecimal;与原有的Long和Double相比,它们处理更大的整数或更大的小数。 这两个类并没有对应的基本类型,并且它们都是以String字符串的形式进行保存和传入。 Number数字类 Number类是一个抽象类。它既是所有数值型包装类的父类,即Byte、Interger、Short、Long、Float、Double的父类,也是BigInterger和BigDecimal的父类。Number类的子类都必须实现Number类中的方法,即将表示的数值转换为byte、int、short、long、float和double的方法。
void类 void类是一个不可实例化的占位符类。它持有一个代表Java关键字void的Class的对象的引用(注意首字母区分大小写),是一个与关键字void一致的伪类型对象。Void类是不允许被其他类继承的,它的作用是类本身,只是一个占位符类,不能被实例化,多用于泛型中做占位符使用。另外,Void是不能使用new关键字来创建一个新对象的,也就是不能在堆里面分配空间来储存对应的值。也就是说,它一开始就在堆栈处分配好空间了。 Math类 Math类中的常量 Math类中的常见方法 三角函数方法 Math类中的三角函数入参和返回值都是double类型的,并且参与三角函数运算都是以弧度为单位,如1°等于Π/180弧度。Math类提供了弧度与角度互相转换的方法。 取整函数方法
void类 void类是一个不可实例化的占位符类。它持有一个代表Java关键字void的Class的对象的引用(注意首字母区分大小写),是一个与关键字void一致的伪类型对象。Void类是不允许被其他类继承的,它的作用是类本身,只是一个占位符类,不能被实例化,多用于泛型中做占位符使用。另外,Void是不能使用new关键字来创建一个新对象的,也就是不能在堆里面分配空间来储存对应的值。也就是说,它一开始就在堆栈处分配好空间了。 Math类 Math类中的常量 Math类中的常见方法 三角函数方法 Math类中的三角函数入参和返回值都是double类型的,并且参与三角函数运算都是以弧度为单位,如1°等于Π/180弧度。Math类提供了弧度与角度互相转换的方法。 取整函数方法
指数函数方法
其数学函数方法 随机数 Math类的random()方法 该方法可以生成大于等于0.0、小于1.0的double型随机数以及生成随机字符。 同时,在Math.random()方法语句的基础上处理,可以获得多种类型或任意范围的随机数。 Random类 除了可以用Math类的random()方法获取随机数之外,还可以通过使用Java.util.Random类将一个Random对象实例化来创建一个随机数生成器。Random类并不在Math类中,之所以在这里对它进行介绍是为了将它和Math类中的random()方法做对比。 Random类初始化对象格式为: Random random =new Random(); 以这种形式将对象实例化时,Java编译器以系统当前时间作为随机数生成器的种子,因为时间是一直在变化的,所以产生的随机数也不同。但是如果程序运行速度太快,也会产生相同的随机数。 可以在将Random类对象实例化时,自定义随机数生成器的种子 Random random =new Random(seedValue); Random类中还提供了各种类型的随机数的生成方法 枚举 枚举是一种特殊的数据类型,它是将一系列含义相同、预先定义好的常量组合起来,其中每个常量都有各自定义好的相同类型的值。使用枚举的好处是它限定了取值的范围,提高了代码编程的安全性和便携性 定义 public enum [枚举类名]{ [枚举值代码块] } 因为枚举和Class类一样,都是需要被外部访问,所以权限修饰符都是public;enum为枚举类型的关键字;枚举类的名称与Class定义相同,一般为首字母大写,因为表示常量,枚举类型的字段一般为大写字母 枚举的特点 ·所有枚举类都是Enum的子类 ·我们可以通过“枚举类名.枚举项名称”去访问指定的枚举项 ·每个枚举项其实就是该枚举的一个对象 ·枚举也是一个类,可以去定义成员变量 枚举的常见方法 枚举集合 枚举类型中也可以添加自定义的构造方法,但是构造方法必须是私有的,被private关键字修饰。 枚举集合 java.util.EnumSet和java.util.EnumMap是两个枚举集合。Enum保证集合中的元素不重复;EumnMap中的key是enum类型,而value则可以是任意类型。
泛型 泛型是 JDK1.5引入的新特性,其本质的参数化类型,也就是说所操作的数据类型可以被指定为一个参数,参数分别有泛型类、泛型接口和泛型方法。 泛型类 和正常类声明相似,泛型类的声明需要使用Class关键字,但是不需要在类名后面添加类型参数声明。 Class [类名]<T> 其中,字母T表示泛型类型,它并没有指定特定的类型,可以是除了基本类型外的任何对象或接口。哦我们可以使用26个英文字母中的任意一个大写字母来表示泛型。 泛型类的类型参数声明可以包含多个类型参数,参数之间需要用逗号隔开。 泛型类定义的类型,可以在类中用来定义成员属性或成员方法的返回值。实际使用时,可以使用具体的类型来替换泛型变量,将泛型类型对象实例化后进行操作。 泛型方法 泛型方法定义格式如下: [权限访问修饰符]<参数类型列表>返回值 方法名称([参数列表]); 泛型方法和其他方法的声明其实是一样的,需要注意类型参数只能是引用类型,而不能是基本类型。 java对象生命周期 创建阶段 应用阶段 不可见阶段 不可达阶段 回收阶段 终止阶段 对象重新分配内存空间阶段 java中常见类库介绍 日志类库 Java打印日志目前最常用的类库有slf4j、log4j、commons logging、logback JSON解析库 JSON是JavaScript Object Notation的缩写,是一种轻量级的数据格式,在目前主流互联网开发中已经逐步取代传统XML数据格式,并且体量更小、更便于解析。Java没有提供原生的对JSON数据格式的解析类库,目前流行的开源类库工具有Jackson库、谷歌的Gson库、JSON-lib库、阿里巴巴的fastjson库、flexjson库。 单元测试库 Java中的单元测试类库通常有JUnit、REST Assured、Selenuim、Mockito、Spring Test、DBUnit、TestNG等。 通用类库 Java中一些常见的第三方通用类库有Apache Commons库、Google Guava库、JMS Java消息类库、Apache FOP库等。 Excel读写库 Java中一些常见的Excel读写库有Apache POI库、JExcelAPI库。 集合类库 集合类库用来操作Java中的集合类,支持判断是否为空集合、集合转换、添加删除集合元素等。 Java常见的集合类库有Apache Commons Collections库、Goldman Sachs Collections库、Google Collections库、FastUtil库、Trove库等。 java集合类 集合类相当于容器,能够储存一系列的对象的引用,其中储存的每个内容称为元素。集合类框架提供了两个接口,Collection与Map,他们都继承了java.lang.Object类。其中,Collection类由List和Set两种继承接口。每种接口都有各自的实现方式;Map是一种键值对的储存形式,同时也有自己的实现。 集合与数组相近,但是定义和功能十分不同。数组大小是固定的,集合的大小则是可变的,数组可用来存放基本类型数据,也可以存放对象的引用,集合存放分只能是对象的引用。 Collection接口 Collection是最基本的集合类接口,可以认为它是描述了一系列相同功能接口的共性接口。Collection接口中提供了通用的对集合内元素操作的方法,Collection的子类会实现这些方法。 注:Collection类只是接口类,并没有提供具体的方法实现。每个方法的实现是在具体的实现类中完成的。 Collection接口同时继承了Iterable接口,因次Collection的所有子类(List类、Set类等)也都实现了Iterable接口。Iterable是java集合的顶级接口之一,这个接口中提供了三个方法,分别forEach()、iterator()和spliterator()。三个方法中最常用的是iterator(),它可以通过迭代器遍历自身元素,也就是查询整个集合的所有元素。 List集合 list接口的实现类由AbstractList、ArrayList、LinkedList、Stack、Vector、AttributeList等。 ArrayList类 ArrayList实现了List接口,同时继承于AbstractList类,实现了可变大小的数组(数组的容量不可变,但是ArrayList的容量可以动态增长),允许由null元素。ArrayList随机访问和遍历整个集合是性能较好,但是在List的指定位置插入和移除元素时性能较差。 ArrayList可以使用get()、set()方法来对指定索引获取、设置特定的元素。 除了Collection中提供的方法,ArrayList还有一些常用的方法付。 注:ArrayList是非同步的,在多线程的情况下要谨慎使用 LinkedList类 使用链表结构进行存储,允许由null元素,在List的中间插入和移除元素时性能较好,但是在随机访问和查询集合中的元素时,性能较差。 注:LinkedList是非同步的,在多线程的情况下要谨慎使用 Set集合 Set与List类似,也支持元素的插入和移除等各种操作。不同的是,Set不能包含重复元素。确切的说,是不能包含满足equals()方法的两个对象(这里不仅指对象,而且也包括具体的某个数值或者字符串);Set不一定保证元素在集合中的顺序,也没有提供get()和set()方法。 Se接口的实现由AbstractSet、HashSet、EnumSet、LinkedHashSet、TreeSet等 HashSet类 HashSet类实现了Set接口,由哈希表支持。它不保证Set内元素的顺序,因此每次在访问或迭代遍历时取出的元素的顺序并不相同。 使用时通常将变量类型声明为Set类型,可以通过具体的实现类来定义不同的对象具体实例化类型。HashSet中提供了默认的构造器HashSet(int initialCapacity),可以初始化一个指定大小的集合。 除了Collection中的基础方法之外,HashSet类并没有提供过多的其他方法。 HashSet是非线程同步的,子啊多线程情况下,如果多个线程同时访问一个HashSet对象,当至少一个线程修改了该对象时,需要使用Collection类中的synchronizedSet()方法来包装,使这个对象对外部保持同步 TreeSet类 TreeSet类同时实现了Set接口和NavigableSet接口。它既可以使用元素的自然顺序对元素进行排苏,也可以根据创建Set集合是提供的Comparator比较器的顺序进行排序,如果没有就会抛出ClassCastException异常。 Comparable接口中提供了compareTo(Object o)方法,用于比较当前对象与传入对象来决定前后顺序。若该对象小于入参对象,则应返回负整数;若相同,则返回0;若大于入参对象,则应返回正整数。 Tree也是非同步,在多线程环境下需谨慎使用 TreeSet中的ceiling、headSet、subSet和tailSet等方法时,需注意取得元素的范围,避免丢失元素。 Map集合 Map接口提供了键值对的储存能力,即key-value。Map中的key是不能重复的,每一个key只能是一对一映射一个value。java中提供了Map。Entry<K,V>接口来描述它们。Map中提供了entrySet()方法来获取所有的Entry集合, Map是在java.util包中提供的,具体实现类由AbstractMap、HashMap、TreeMap、HashTable、LinkedHashMap、EunmMap等。 HashMap 利用哈希值来储存数据,不允许重复的键出现,但允许由null值和null键,(最多只允许一个为null的键)。HashMap使用了哈希表,所以对其中的映射关系具有很快的访问速度。HashMap类不保证存入键值对映射关系的顺序,而且它的顺序可能发生变化。 使用时通常将变量类型声明为Map类型,可以通过具体的实现类来定义不同对象的具体实例化类型。 HashMap是非线程同步的,所以在多线程的情况下要谨慎使用。 TreeMap TreeMap实现了Map接口,继承于AbstractMap类,同时实现了NavigableMap接口。TreeMap是基于红黑树结构的,因此存储键值对具有一定的顺序。与TreeSet类似,TreeMap既可以使用键值对映射的自然顺序对映射关系进行排序,也可以根据创建Map集合时提供的Comparator比较器的顺序进行排序。若无排序,就会抛出ClassCastException异常。TreeMap因为引入了顺序,查询性能比HashMap稍差。与HashMap不同的是,它不允许存在null的键对象。 在使用时,为了使用TreeMap中的方法,一般会声明为TreeMap类型。 TreeMap也是非同步的,一般会使用Collections。synchronizedSortedMap()方法来包装该映射。 Collections算法 Collections包含以下三个常量: EMPTY_LIST——空的List列表 EMPTY_MAP——空的映射Map EMPTY_SET——空的Set集合 sort()排序方法 指定元素的自然顺序,对集合按升序进行排列。集合中的所有元素都必须实现Comparable接口,并且都可以使用比较器进行相互比较 shuffle()混排方法 与sort()方法相反,Collections.shuffle()方法用来随机打乱集合中元素的顺序。 reverse()反转方法 使用Collections.reverse() 方法可以将集合中的元素按照当前排序进行反向排列

java反射与注解

Java反射 java.lang.Class类的介绍 java编程中的每一个类都是一个对象,是java.lang.Class类的对象。即每一个类既有自己的对象,同时也有Class类的对象。由于Class类的构造方法是私有的,因此我们无法通过new关键字创建Class对象的引用,但是java中提供了几种获取Class对象的方法。 方法一:通过对象的getClass()方法获取Class对象的引用 [对象名].getClass 方法二:任何类都有一个隐含的静态成员变量class,通过改静态成员获取Class对象的引用 [类名].class 方法三:使用Class类的静态方法forName(),它使用一个包含目标类的字符串作为输入,返回一个Class对象的引用。因为这个方法传入的是一个字符串形式的类路径,所以通过该方式获取Class对象时需要处理ClassNotFoundException异常,该异常代表找不到类或者类无法加载。 Class [Class类名]=Class.forName(" ")//传入某类 的项目路径 注:一个类只能由一个反射的对象。 获取构造方法的信息 通过Class类的getConstructors()、getConstructor()、getDeclaredConstructor()和getDeclaredConstructo()方法可以访问类的构造方法,它们的返回值类型为Constructor对象或者对象的数组。 java.lang.reflect.Constructor类提供了单个构造方法的信息,利用Constructor对象即可操作操作相应的构造方法。 获取成员变量的信息 通过Class类中提供的getField()、getFields()、getDeclaredFirld()和getDeclaredFields()方法可以获取类的成员变量信息。它们的返回值为Field对象或者对象数组,各种方法的详细描述。 java.lang.reflect.Field提供了获取当前对象的成员变量的类型和重新设值的方法。、
获取方法的信息 通过Class类中提供的getMethod(),getMethods()、getDeclaredMethod()和getDeclaredMethods()方法可以获取类的方法信息。它们的返回值为Method对象或者对象数组。 通过Method对象可以操作相应类的方法,Method类常用的方法如下
注解 元注解 jDK 1.5中定义了四个标准的元注解类型:@Target、@Retention @Documented和@Inherited。这些注解可以在java.lang.annitation包中找到,下面分别讲解每个元注解的作用 @target描述了注解修饰的对象范围,他的取值在java.lang.annotation.ElementType中定义 @Retention代表注解保留的时间,有些注解进存在于源码中,有些在编译过程中会被丢弃,有些会偕同源码一起被编译进class文件中。编译在class文件中的注解可能会被虚拟机忽略,也可能会在class文件装载时读取。其取值在java.lang.annotation.RetentionPolicy中定义。 @Inherited表示一个注解类型会被自动继承。当开发者自定义注解时,标注在父类上的自定义的注解不会被子类所继承,但是可以在定义注解时给自定义的注解标注一个@INherited注解来实现吧注解的继承。 @ocumented表示使用该注解的元素应被javadoc文档化。如果一个类型声明时添加了@Documented注解,那么它的注解会成为被注解元素的公共API的一部分。 内置注解介绍 JDK1.5中共定义了七个注解,三个位于java.lang包中,其余四个在java.lang.annotation包中。其中位于java.lang包中的三个时作用在代码上的注解。 @Override时一个标记注解类型,标注在方法上,用于检查方法是否为重写方法。如果在一个没有覆盖父类方法的方法上使用@Override 注解,java编译器将以一个编译错误来警示 @Deprecated也是一个标记注解,用于标记已过时的方法。当一个类型或者类型成员使用@Deprecated修饰时,编译器会将不建议使用被@Deprecated标注的方法。如果依旧在代码中使用该方法,将会报出编译警告 @SuppressWarnings用于指示编译器忽略注解中声明的警告,它有一个类型为String数组的成员,这个成员的值为要被忽略的警告名。 自定义注解 在java中,可以使用@interface关键字来创建自定义注解。创建自定义注解时要注意:自定义注解需要加上元注解来描述注解的使用方式和范围;自定义注解不能继承其他的注解或者接口; 可以通过default来声明参数的默认值;和接口类似,注解中的方法不允许使用protected、private修饰符,也无须加public的修饰符,保持默认即可。 注解的解析需要用到Java的反射机制。 注:Retention的取值应为RetentionPolicy.RUNTIME,为的是能够在程序运行中获取注解的相关信息。 Spring注解 Spring框架的一个核心功能是控制反转IOC,通过IOC可以将Spring的Bean值初始化并加载到Spring容器中,而加载Bean到Spring容器的其中一种方式就是使用注解。 Spring中常用的注解 @Component是一个元注解,当标注在一个类上时,该类会成为被Spring管理的Bean,将@Conponent加入到应用上下文中 @Controller是一个组合注解,组合了@Component,它应用在MVC层,DispatcherServlet会自动扫描注解了此注解的类,然后将Web请求映射到注解了@RequestMapping的方法上。 @Service是一个组合注解,组合了@Component,时@Componnet注解的一种具体形式。他应在service层(业务逻辑层),执行业务逻辑、计算、调用内部API等。 @Repository是一个组合注解,组合了@Component,它应用在DAO层(数据访问层),用于访问数据库 @Autowired注解作用于Bean的field、setter方法以及构造方法上。当在field上使用此注解,并且使用属性来传递值时,Spring会自动吧值赋给此field。 动态代理 代理模式为其他的对象提供一种代理以控制对这个对象的访问。某种情况下,一个客户对象不适于或不能直接应用目标对象,而使用代理对象则可以在客户对象和目标对象之间起到一个中介的作用。简单来说,代理模式是为了在不修改目标对象的基础上增强主业务的逻辑。 在程序运行时有JVM通过反射等机制生成代理类的方式被称为动态代理。动态代理类并不是在Java代码中定义的,代理对象于目标对象的代理关系是在程序运行中才确定的。 使用java.lang.reflect.Proxy类的静态方法newProxyINstance(),依据目标对象、业务接口及业务增强逻辑三者来自动生成一个动态代理对象。 newProxyInstance()方法的源码声明如下
◇ loader:目标类的类加载器,可以通过目标对象的反射来获取 ◇ interfaces:目标类实现的接口数组,可以通过目标对象的反射来获取 ◇ handler:业务增强逻辑,需要在定义。它需要实现InvocationHandler接口,用以加强目标类的主业务逻辑。这个接口中会有一个invoke()方法,具体加强的代码逻辑就是在该方法中定义的。程序调用主业务逻辑时,会自动调用invoke()方法。

java时间与日期

操作日期主要涉及以下几类: 1.java.util.Date 表示特定的时间,已废弃 2.java.text.DateFormat 是日期时间格式化的抽象类, 3.java.util.calendar Calendar是定义日期的抽象类 4.java.text.SimpleDateFormat SimpleDateFormat类是DateFormat类的子类,用来在特定语言环境下格式化或分析日期的类。 SimpleDateFormat类支持日期时间和文本按照一定标准互相转化。java中定义时间日期的格式“yyyy-MM-dd HH:mm:ss” Date类 构造方法 Date类中常用的方法 Calendar类 Calendar类是一个抽象类,它为特定时间、年、月、日、小时、等之间的转换提供了操作方法,也为获取日历和操作日历提供了便捷的方法。 Calendar类不能直接用new关键字来初始化对象,但它提供了getInstance()方法,用来获得Calendar类的对象,并且通过使用当前系统的日期和时间初始化对象。 calendar cal=Calendar.getInstance();//得到的是GregorianCalendar对象 Calendar也支持设置特定时间,此时需要使用Calendar对象的set()方法 Calendar类中提供了很多常用的成员属性,可以直接使用 Calendar类中提供了get()方法,可以获取日期时间的指定内容。 DateFormat类 DateFormat类是java.text包提供的,用以日期时间格式化的抽象类。他提供了很多方法和可供参考的格式化风格。 DateFormat类为抽象类,所以实例化对象不能使用new关键字,需要通过工厂类的方法返回DateFormat的实例,即 DateFormat dateFormat=DateFormat.getDateInstance(); DateFormat类提供了parse()方法,可以将字符串转为Date对象,以及通过format()方法,可以将Date对象转为字符串。 DateFormat不是同步的,在多线程编程中,建议为每一个线程穿件独立的格式实例;多个线程同时访问一个DateFormat对象时,它必须保持外部同步。 SimpleDateFormat类 SimpleDateFormat类是DateFormat类的子类,与DateFormat不同的是,SimpleDateFormat是与本地的语言环境相关的,允许选择任何用户自定义的日期时间格式。另外SimpleDateFormat可以通过new关键字创建实例化对象。 SimpleDateFormat类重写了parse()和format()方法,可以将字符串转为Date对象,也可以将Date对象转为指定日期时间格式的字符串。 SimpleDateFormat不是线程安全的,因此在java 8中引入了新的类—java.time.format.DateTimeFormat类,用于解析和格式化日期时间。DateTimeFormat是线程安全的,也可以完成字符串与日期时间对象的相互转化。 时区划分 全球分为24个时区,每个时区都有自己的本地时间,同一时刻各时区的本地时间相差1~23小时。北京时间为东八区。在国际无线电通信领域,使用一个统一的时间,该时间称为通用协调时间(UTC),UTC与格林尼治标准时间(GMT)相同。 Unix时间戳 在Unix系统中,日期与时间表示为自1970年1月1日零点起到当前时间的秒数,这种时间被称为Unix时间戳(Unix timestamp),以32位二进制数表示。不同操作系统均支持这种时间表示方式,同一时间在Unix和Windows中均以相同的Unix时间戳表示,所以不需要在不同的系统中进行转换。目前Unix时间戳能表示的最大时间为2038年1月19日3点14分7秒。 java与Unix时间戳 使用System.currentTimeMillis()方法获取操作系统的时间戳; Unix时间戳和格式化日期之间可以互相转换。

java I/O流

java I/O,即Java Input or Output,是指java中对流处理的方式。操作的流可以是文件、网络请求数据、压缩包、Excel文档等。Java.io包中提供了负责各种方式的输入输出的操作方法,同时也支持各种格式,比如基本类型、对象等。 输入/输出流 输入流 输入流分为两种:字节输入流InputStream类,和字符输入流Reader类。 InputStream类 InputStream类是所有字节输入流类的父类,是一个抽象类。 InputStream类中所有方法在调用时 都会抛出IOExcepiton异常,表示在处理输入、输出流时发生的问题异常。 Reader类 InputStreamlei是用来处理字节流的,但是在java环境中,字符文本都是Unicode编码,是双字节的,不适合使用InputStream来进行处理。Reader类,专门用于处理字符流,降低了开发成本。Reader类是所有字符输入流类的父类,它的子类有:BufferedReader、CharArrayReader、FilterReader、InputStreamReade、PipedReader、StringReader Reader类中的成员方法 注:ready()方法用来判断输入流是否准备就绪,这个判断逻辑在一个文件很大、读取速度很慢时非常有用。 输出流 OutputStream类 OutputStream类是所有字节输出流类的父类,是一个抽象类。包括:ByteArrayOutStream、FileOutputStream,FilterOutputStream、ObjectOutputStream、PipedOutputStream、org.OMG.CORBA.portable.OutputStream。 OutputStream类中所有的成员方法均定义为void,没有返回参数,遇到错误异常时也会抛出IOException异常。 write类 Write类是所有字符输出流类的父类,是一个抽象类。子类有BufferedWirter、CharArrayWriter、FilterWriter、OutputStreamWriter、PipedWriter、printWriter、StringWriter。 系统预定义流 在java中,系统预先定义好了几个流变量。在java程序运行时,会自动导入java.lang包,其中定义了System类,该类封装了程序运行环境的各种参数。System类中包含三个预定义的流变量,分别为System.in 、System.out和 System.err。它们都被public和static关键字修饰,可以在不引用特定的System对象的情况下,在程序的特定地方直接被调用。 System.in 表示标准输入流,对应键盘的输入或控制台的输入。System.in 为InputStream类型的对象 System.out表示标准输出流,对应计算机的显示器。System.out为PrintStream类型的对象,在程序中可以直接使用System.out打印到控制台。 System.err表示标准错误输出流,一般情况下,错误输出流在系统运行时就已打开准备接受数据。 File类 Java使用file累来表示计算机系统磁盘文件的对象类型。
通过入参指定字符串格式的路径名称(包括文件名),将它转换为抽象的路径名来创建一个File对象
File文件基本操作 File类中提供了操作文件的方法,也可以直接对文件夹进行操作。文件常见操作有:判断文件是否存在,创建和重命名文件,删除文件和获取文件基本信息。
File类也支持对文件夹的操作。对文件夹的操作一般有创建文件夹、删除文件夹、判断文件夹是否存在、获取文件夹信息等。
文件输入/输出流
缓存输入/输出流 数据输入/输出流

java序列化

java异常处理

异常处理定义 异常处理关键字 常见异常 自定义异常 使用异常的若干建议

多线程与并发

Java线程机制 java程序都是在JVM上运行的,程序中的很多任务也都依赖JVM的线程调度。程序代码执行任务是由线程来完成的,每个线程在JVM中都有独立的计数器和方法调用栈。计数器是计算机中特殊的寄存器,用来记录线程当前执行程序代码的位置,同时也标记下一跳要执行语句。方法调用栈是由来表示线程执行一系列方法调用的参数、局部变量和程序执行中的临时变量。 JVM在运行是只会同时运行一个JVM进程。在JVM进程中,程序都是以线程运行的;JVM启动时会产生一个主线程,指定程序的起始入口,主线程运行结束时,JVM进程也会终止运行。这种只有一个线程运行的程序流程,被称为单线程。在线程中同时可以创建新的线程来运行,此时在一个JVM进程中就存在多个线程同时运行,被称为多线程。 线程的初始化和调用 创建一个线程有两种方法,继承Thread类和实现Runnable接口。 继承Thread类 Thread类在Java.lang包中,每个Thread类的实例对象代表一个线程,其子类的实例对象也代表一个线程。 Thread类包含常用的构造方法如下
使用Thread类创建并执行线程的具体步骤如下 1.创建Thread类的子类 2.重写Thread类中的run()方法 3.创建Thread子类对象,即创建一个线程对象 4.调用线程对象的start()方法启动线程,之后系统会自动调用重写的run()方法中的具体实现。 创建线程对象后,JVM内存中仅会出现一个Thread类的实例对象,线程并不会自动运行,必须调用线程对象的start()方法来启动线程。实际完成线程功能的代码位于重写的run()方法中,调用start()方法时会先分配线程所需的内存资源,再调用run()方法运行线程。 注:未调用start()方法,线程永远不会启动。在start()方法被调用前,Thread对象只是一个对象,并没有真正意义上的线程。
实现Runnable接口
类实现Runnable接口的定义如下
实际上,Thread类也是实现了Runnable接口。实现Runnable接口的类在实例化时,会创建一个Thread对象,并将Thread对象与Runnable对象相关联。Runnable接口中只有一个方法--run()方法,声明类时要实现run()方法。使用Runnable接口来创建和启动线程的具体步骤如下: 1.定义实现Runnable接口的类,实现run()方法 2.创建Runnable对象并作为Thread类的target参数来创建Thread对象(实际的线程对象) 3.调用start()方法启动线程。 实现Callable和Future接口 Callable接口是Java 5新增的接口,位于java.util.concurrent包中,其使用类似于Runnable。Callable接口中提供了call()方法,被调用时用来执行线程,并且会有返回值,返回值类型为Future接口的实现类。同时,call()方法声明了抛出异常。 Future接口是与Callable接口配合使用的,也位于java.util.concurrent包中,提供了用来检测线程是否被执行完成的方法,并在任务执行完成时获得结果。另外,Future接口支持设置线程执行的超时时间。 Callable接口的定义如下
FutureTask类同时实现了Runnable接口和Future接口,可以作为Thread类的target入参来创建线程,同时也可以使用Future接口中的call()方法来获取返回值。 使用Callable接口和Future接口创建并启动线程的步骤如下: 1.声明实现Callable接口的类,实现call()方法,并定义返回值类型; 2.创建实现Callable类的对象,使用FutureTask类包装Callable对象; 3.创建Thread对象,使用FutureTask对象作为Thread对象的target入参,并启动线程; 4.使用FutureTask对象的get()方法来获取线程结束后的返回值。 线程的生命周期 1.创建状态 2.就绪状态 3.运行状态 4.阻塞状态 5.死亡 优先级 Java操作线程 加入线程 休眠线程 中断线程 线程的同步 线程安全 线程的同步机制 1.同步代码块 2.同步方法 线程暂停与恢复 死锁

🤗 总结归纳

总结文章的内容

📎 参考文章

  • 一些引用
  • 引用文章
💡
欢迎您在底部评论区留言,一起交流~
用openlist挂载网盘 (1)加锁文章
Loading...