Java学习——复习 第六天--枚举泛型、输入输出流、反射
10.枚举与泛型
(1)枚举—是一种数据类型,他是一系列具有名称的常量的集合
1.1使用枚举类型设置常量
语法: public enum Constants{
Constants_A,Constants_B,Constants_C
}
enum是定义枚举类型的关键字。当需要在使用该常量时,可以使用Constants. Constants_A来表示。
代码说明:
interface Constants { // 将常量放置在接口中
public staticfinal int Constants_A = 1;
public staticfinal int Constants_B = 12;
}
public class ConstantsTest {
enum Constants2{ // 将常量放置在枚举类型中
Constants_A,Constants_B
}
// 使用接口定义常量
public staticvoid doit(int c) { // 定义一个方法,这里的参数为int型
switch(c) { // 根据常量的值做不同操作
caseConstants.Constants_A:
System.out.println("doit()Constants_A");
break;
caseConstants.Constants_B:
System.out.println("doit()Constants_B");
break;
}
}
public staticvoid doit2(Constants2 c) { // 定义一个参数对象是枚举类型的方法
switch(c) { // 根据枚举类型对象做不同操作
case Constants_A:
System.out.println("doit2()Constants_A");
break;
case Constants_B:
System.out.println("doit2()Constants_B");
break;
}
}
public staticvoid main(String[] args) {
ConstantsTest.doit(Constants.Constants_A);// 使用接口中定义的常量
ConstantsTest.doit2(Constants2.Constants_A);// 使用枚举类型中的常量
ConstantsTest.doit2(Constants2.Constants_B);// 使用枚举类型中的常量
ConstantsTest.doit(3);
//ConstantsTest.doit2(3);
}
结果:
doit() Constants_A
doit2() Constants_A
doit2() Constants_B
在上述代码中,当用户调用doit()方法时,即使编译器不接受在接口中定义的常量参数。也不会报错,但调用doit2()方法,任意传递参数,编译器就会报错,因为这个方法只接受枚举类型的常量作为其参数。
1.2深入了解枚举类型
1)操作枚举类型成员的方法
用户可以将一个枚举类型看作是一个类,它继承于java.lang.Enum类,当定义一个枚举类型时,
每一个枚举类型成员都可以看作是枚举类型的一个实例,这些枚举类型成员都默认被 final.public.suatic 修饰,所以当使用枚举类型成员时直接使用枚举类型名称调用枚举类型成员即可。
枚举类型的常用方法 | ||
方法名称 | 具体含义 | 使用方法 |
values() | 该方法可以将枚举类型成员以数组的形式返回 | 枚举类型名称.values() |
valuesOf() | 该方法可以实现将普通字符串转化为枚举实例 | 枚举类型名称.valuesOf(“abc”) |
compareTo() | 该方法用于比较两个枚举对象在定义时的顺序 | 枚举对象.compareTo() |
ordinal() | 该方法用于得到枚举成员的位置索引 | 枚举对象.ordinal |
values()--枚举类型实例包含一个values()方法,该方法可以将枚举类型成员以数组的形式返回。
代码实现
import static java.lang.System.out;
public class ShowEnum {
enum Constants2{ // 将常量放置在枚举类型中
Constants_A,Constants_B
}
// 循环由values()方法返回的数组
public staticvoid main(String[] args) {
for (inti = 0; i < Constants2.values().length; i++) {
// 将枚举成员变量打印
out.println("枚举类型成员变量:"+ Constants2.values()[i]);
}
}
}
结果
枚举类型成员变量:Constants_A
枚举类型成员变量:Constants_B
valuesOf()与compareTo()--枚举类型中静态方法valueOf()可以将普通字符串转换为枚举类型,而compareTo()方法用于比较两个枚举类型成员定义时的顺序。调用compareTo()方法时,如果方法中参数在调用该方法的枚举对象位置之前,则返回正整数;如果两个互相比较的枚举成员位置相同,则返回0;如果方法中参数在调用该方法的枚举对象位置之后,则返回负整数。
代码实现:
import static java.lang.System.out;
public class EnumMethodTest {
enumConstants2 { // 将常量放置在枚举类型中
Constants_A,Constants_B, Constants_C, Constants_D
}
//定义比较枚举类型方法,参数类型为枚举类型
publicstatic void compare(Constants2 c) {
//根据values()方法返回的数组做循环操作
for(int i = 0; i < Constants2.values().length; i++) {
//将比较结果返回
out.println(c+ "与" + Constants2.values()[i] + "的比较结果为:" + c.compareTo(Constants2.values()[i]));
}
}
//在主方法中调用compare()方法
publicstatic void main(String[] args) {
compare(Constants2.valueOf("Constants_B"));
}
}
结束:
Constants_B与Constants_A的比较结果为:1
Constants_B与Constants_B的比较结果为:0
Constants_B与Constants_C的比较结果为:-1
Constants_B与Constants_D的比较结果为:-2
ordinal()--用于获取某个枚举对象的位置索引值
代码实现
import static java.lang.System.out;
public class EnumIndexTest {
enumConstants2 { // 将常量放置在枚举类型中
Constants_A,Constants_B, Constants_C
}
publicstatic void main(String[] args) {
for(int i = 0; i < Constants2.values().length; i++) {
//在循环中获取枚举类型成员的索引位置
out.println(Constants2.values()[i]+ "在枚举类型中位置索引值" +Constants2.values()[i].ordinal());
}
}
}
结果
Constants_A在枚举类型中位置索引值0
Constants_B在枚举类型中位置索引值1
Constants_C在枚举类型中位置索引值2
2)枚举类型中的构造方法—构造方法必须为private修饰符或者默认修饰符所修饰。方法如下:
publicenum Constants2{
Constants_A(“我是枚举成员A”),
Constants_B(“我是枚举成员B”),
Constants_C(“我是枚举成员C”),
Constants_D(3);
Stringdescription;
inti;
privateConstants2(){ //定义默认构造方法
}
private Constants2(String description){//定义带有参数的构造方法,参数类型为字符串型
this.description=description;
}
private Constants2(int i){//定义带有参数的构造方法,参数类型为整型
this.i=this.i+1;
}
}
代码实现
import static java.lang.System.out;
public class EnumConTest {
enum Constants2{ // 将常量放置在枚举类型中
Constants_A("我是枚举成员A"),// 定义带参数的枚举类型成员
Constants_B("我是枚举成员B"),Constants_C("我是枚举成员C"), Constants_D(3);
privateString description;
privateint i = 4;
privateConstants2() {
}
// 定义参数为String型的构造方法
privateConstants2(String description) {
this.description= description;
}
privateConstants2(int i) { // 定义参数为int型的构造方法
this.i= this.i + i;
}
publicString getDescription() { // 获取description的值
returndescription;
}
public intgetI() { // 获取i的值
returni;
}
}
public staticvoid main(String[] args) {
for (inti = 0; i < Constants2.values().length; i++) {
out.println(Constants2.values()[i]+ "调用getDescription()方法为:" + Constants2.values()[i].getDescription());
}
out.println(Constants2.valueOf("Constants_D")+ "调用getI()方法为:" + Constants2.valueOf("Constants_D").getI());
}
}
结果
Constants_A调用getDescription()方法为:我是枚举成员A
Constants_B调用getDescription()方法为:我是枚举成员B
Constants_C调用getDescription()方法为:我是枚举成员C
Constants_D调用getDescription()方法为:null
Constants_D调用getI()方法为:7
另一代码实现
import static java.lang.System.out;
interface d {
public StringgetDescription();
public intgetI();
}
public enum AnyEnum implementsd {
Constants_A{ // 可以在枚举类型成员内部设置方法
publicString getDescription() {
return("我是枚举成员A");
}
public intgetI() {
returni;
}
},
Constants_B{
publicString getDescription() {
return("我是枚举成员B");
}
public intgetI() {
returni;
}
},
Constants_C{
publicString getDescription() {
return("我是枚举成员C");
}
public intgetI() {
returni;
}
},
Constants_D{
publicString getDescription() {
return("我是枚举成员D");
}
public intgetI() {
returni;
}
};
private staticint i = 5;
public staticvoid main(String[] args) {
for (inti = 0; i < AnyEnum.values().length; i++) {
out.println(AnyEnum.values()[i]+ "调用getDescription()方法为:" + AnyEnum.values()[i].getDescription());
out.println(AnyEnum.values()[i]+ "调用getI()方法为:" + AnyEnum.values()[i].getI());
}
}
}
结果
Constants_A调用getDescription()方法为:我是枚举成员A
Constants_A调用getI()方法为:5
Constants_B调用getDescription()方法为:我是枚举成员B
Constants_B调用getI()方法为:5
Constants_C调用getDescription()方法为:我是枚举成员C
Constants_C调用getI()方法为:5
Constants_D调用getDescription()方法为:我是枚举成员D
Constants_D调用getI()方法为:5
1.3使用枚举类型的优势
1)类型安全
2)紧凑有效的数据定义
3)可以和程序其他部分完美交互
4)运行效率高
(2)泛型
2.1回顾向上、向下转型
代码实现
public classTest {
privateObject b; // 定义Object类型成员变量
publicObject getB() { // 设置相应的getXXX()方法
returnb;
}
publicvoid setB(Object b) { // 设置相应的setXXX()方法
this.b= b;
}
publicstatic void main(String[] args) {
Testt = new Test();
t.setB(newBoolean(true)); // 向上转型操作
System.out.println(t.getB());
t.setB(newFloat(12.3));
Floatf = (Float) (t.getB()); // 向下转型操作
System.out.println(f);
}
}
结果:
true
12.3
2.2定义泛型类
代码实现:
public classOverClass<T> {//定义泛型类
privateT over; // 定义泛型成员变量
publicT getover() { // 设置相应的getXXX()方法
returnover;
}
publicvoid setover(T over) { // 设置相应的setXXX()方法
this.over= over;
}
publicstatic void main(String[] args) {
//实例化一个Boolean型对象
OverClass<Boolean>over1=new OverClass<Boolean>();
//实例化一个Float型对象
OverClass<Float>over2=new OverClass<Float>();
over1.setover(true);//不需要进行类型转换
over2.setover(12.3F);
Booleanb=over1.getover();//不需要进行类型转换
Floatf=over2.getover();
System.out.println(b);
System.out.println(f);
}
}
结果:
true
12.3
2.3泛型的常规用法
1)定义泛型类时声明多个类型
语法:MutiOverClass<T1,T2> MutiOverClass:泛型类名称
2)定义泛型类时声明数组类型—可以声明数组类型
代码实现:
public classArrayClass<T> {
privateT[] array; // 定义泛型数组
publicvoid SetT(T[] array) { // 设置SetXXX()方法为成员数组赋值
this.array= array;
}
publicT[] getT() { // 获取成员数组
returnarray;
}
publicstatic void main(String[] args) {
ArrayClass<String>a = new ArrayClass<String>();
String[]array = { "成员1", "成员2", "成员3", "成员4", "成员5" };
a.SetT(array);// 调用SetT()方法
for (int i = 0; i <a.getT().length; i++) {
System.out.println(a.getT()[i]);// 调用getT()方法返回数组中的值
}
}
}
结果:
成员1
成员2
成员3
成员4
成员5
3)集合类声明容器的元素—通过在集合类中应用泛型可以使集合类中的元素类型保证唯一性,提高代码的安全性和可维护性
代码实现:
importjava.util.HashMap;
importjava.util.Map;
public classMutiOverClass<K, V> {
publicMap<K, V> m = new HashMap<K, V>(); // 定义一个集合HashMap实例
//设置put()方法,将对应的键值与键名存入集合对象中
publicvoid put(K k, V v) {
m.put(k,v);
}
publicV get(K k) { // 根据键名获取键值
returnm.get(k);
}
publicstatic void main(String[] args) {
//实例化泛型类对象
MutiOverClass<Integer,String> mu = new MutiOverClass<Integer, String>();
for(int i = 0; i < 5; i++) {
//根据集合的长度循环将键名与具体值放入集合中
mu.put(i,"我是集合成员" + i);
}
for(int i = 0; i < mu.m.size(); i++) {
//调用get()方法获取集合中的值
System.out.println(mu.get(i));
}
}
}
结果:
我是集合成员0
我是集合成员1
我是集合成员2
我是集合成员3
我是集合成员4
常用的被泛型化的集合类 | |
集合类 | 泛型定义 |
ArrayList | ArrayList<E> |
HashMap | HashMap<K,V> |
HashSet | HashSet<E> |
Vector | Vector<E> |
代码实现
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class ListClass {
publicstatic void main(String[] args) {
// 定义ArrayList容器,设置容器内的值类型为Integer
ArrayList<Integer>a = new ArrayList<Integer>();
a.add(1);// 为容器添加新值
for(int i = 0; i < a.size(); i++) {
//根据容器的长度循环显示容器内的值
System.out.println("获取ArrayList容器的值:" + a.get(i));
}
// 定义HashMap容器,设置容器的键名与键值类型分别为Integer与String型
Map<Integer,String> m = new HashMap<Integer, String>();
for(int i = 0; i < 5; i++) {
m.put(i,"成员" + i); // 为容器填充键名与键值
}
for(int i = 0; i < m.size(); i++) {
//根据键名获取键值
System.out.println("获取Map容器的值" + m.get(i));
}
// 定义Vector容器,使容器中的内容为String型
Vector<String>v = new Vector<String>();
for(int i = 0; i < 5; i++) {
v.addElement("成员" + i); // 为Vector容器添加内容
}
for(int i = 0; i < v.size(); i++) {
//显示容器中的内容
System.out.println("获取Vector容器的值" + v.get(i));
}
}
}
结果
获取ArrayList容器的值:1
获取Map容器的值成员0
获取Map容器的值成员1
获取Map容器的值成员2
获取Map容器的值成员3
获取Map容器的值成员4
获取Vector容器的值成员0
获取Vector容器的值成员1
获取Vector容器的值成员2
获取Vector容器的值成员3
获取Vector容器的值成员4
2.4泛型的高级用法
1)通过类型参数T的继承限制泛型类型—可以使用任何类型来实例化一个泛型类对象,使用泛型限制后,泛型类的类型必须实现或继承了anyClass这个借口或类。
代码实现:
publicclass LimitClass<T extends List>{//限制泛型的类型
public static void main(String []args){
LimitClass<ArrayList> l1=new LimitClass<ArrayList>();
LimitClass<LikedList> l2=new LimitClass< LikedList>();
//HashMap没有List()接口
}
}
2)通过类型通配符的继承限制泛型类型—在创建一个泛型对象时,限制这个泛型类的类型,或者限制这个泛型类型必须继承某个接口或某个类。
语法:泛型类名称<?extends List> a=null;
代码实现:
public classWildClass {
publicstatic void main(String[] args) {
List<String>l1 = new ArrayList<String>(); // 创建一个ArrayList对象
l1.add("成员"); //在集合中添加内容
List<?>l2 = l1; // 使用通配符
List<?>l3 = new LinkedList<Integer>();
System.out.println("l1:"+ l1.get(0)); // 获取l1集合中第一个值
System.out.println("l2:"+ l2.get(0)); // 获取l2集合中第一个值
l1.set(0,"成员改变"); // 没有使用通配符的对象调用set()方法
//l2.set(0, "成员改变"); // 使用通配符的对象调用set()方法,不能被调用
//l3.set(0, 1);
System.out.println("l1:"+ l1.get(0)); // 可以使用l1的实例获取集合中的值
System.out.println("l2:"+ l2.get(0)); // 可以使用l2的实例获取集合中的值
}
}
结果:
l1:成员
l2:成员
l1:成员改变
l2:成员改变
3)继承泛型类与实际泛型接口—定义为泛型的类和接口是可以被继承和实现的
用法展示:泛型类的继承
public class ExtendClass<T1>{
}
class SubClass<T1,T2,T3> extendsExtendClass<T1>{
}
泛型接口的继承
interfaceTestInterface<T1>{
}
class SubClass<T1,T2,T3> implementsTestInterface <T1>{
}
2.5泛型总结
1)泛型的类型参数只能是类类型,不可以是简单类型,如A<int>这种泛型定义是错误的
2)泛型的类型可以是多个的
3)可以使用extends关键字限制泛型的类型
4)可以使用通配符限制泛型的类型
11.I/O(输入/输出)流
(1)流概述—将不同输入输出设备(例如文件、网络、压缩包等)之间的数据传输抽象为流,根据流中传输的数据类型,可以将流分为字节流(以Stream结尾的流)和字节流(以Reader和Writer结尾的流)两种,而根据流的操作模式,可以将流分为输入流和输出流两种
(2)输入/输出流
2.1输入流
1)InputStream类—是字节输入流的抽象类,是所有字节输入流的父类。
InputStream类的常用方法 | ||
方法 | 返回值 | 说明 |
read() | int | 从输入流中读取数据的下一个字节。返回0-255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值-1 |
read(byte[]b}) | int | 从输入流中读入一定长度的字节,并以整数的形式返回字节数 |
mark(int readlimit) | void | 再输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效前允许读取的字符数 |
reset() | void | 将输入指针返回到当前所做的标记处 |
skip(long n) | long | 跳过输入流上的n个字节并返回实际跳过的字节数 |
markSupported) | boolean | 如果当前流支持mark()/reset()操作就返回True |
close() | void | 关闭此输入流并释放与该流关联的所有系统资源 |
2)Reader类—是字符输入流的抽象类,方法与InputStream类的方法类似,另提供一个ready()方法,该方法用来判断是否准备读取流,返回Boolean类型值
2.2输出流
1)OutputStream类—是字节输出流的抽象类
OutputStream类的常用方法 | |
方法 | 说明 |
write(int b) | 将指定的字节写入此输出流 |
write(byte [] b) | 将b个字节从指定的byte数组写入此输出流 |
write(byte[] b,int off,int len) | 将指定byte数组中偏移量off开始的len个字节写入此输出流 |
fiush() | 彻底完成输出并清空缓冲区 |
close() | 关闭输出流 |
2)Writer类—是字符输出流的抽象类
Writer类的常用方法 | |
方法 | 说明 |
append(char c) | 将指定字符添加到此write |
append(CharSequeence csq) | 将指定字符序列添加到此write |
append(CharSequeence csq,int start,int end) | 将指定字符序列的子序列添加到此write.Appendable |
close() | 关闭此流,但要先刷新它 |
flush() | 刷新该流的缓冲 |
write(char[]cbuf) | 写入字符数组 |
write(char[]cbuf,int off,int len) | 写入字符数组的某一部分 |
write(int c) | 写入单个字符 |
write(String str) | 写入字符串 |
write(String str,int off,int len) | 写入字符串的某一部分 |
(3)File类—是java.io包中唯一有个代表磁盘文件本身的对象,主要用来获取磁盘文件信息
3.1创建File对象—通常用以下三种方法创建文件对象
1)new File(Stringpathname)其中pathname用来指路径的名称(包含文件名)。
2)new File(Stringparent,String child)parent:父路径字符串。例如D:/;child:子路径字符串(包含文件名)。例如 letter.java;
3)new File(File parent,String child)parent :抽象父路径对象。例如D:/doc/;child:子路径字符串(包含文件名)。例如 letter.java;
3.2文件操作
File类中对文件进行操作的常用方法 | ||
方法 | 返回值 | 说明 |
canRead() | boolean | 判断文件是否是可读的 |
canWrite() | boolean | 判断文件是否可被读入 |
createNewFile() | boolean | 当且仅当不存在具有指定名称的文件时,创建一个新的空文件夹 |
createTempFile(String prefix,String suffix) | File | 在默认临时文件夹中创建一个空文件夹,使用给定前缀和后缀生成其名称 |
createTempFile(String prefix,String suffix,File directory) | File | 在指定文件夹中创建一个空文件夹,使用给定前缀和后缀生成其名称 |
delete() | boolean | 删除指定的文件夹或文件夹 |
exists() | boolean | 测试指定的文件夹或文件夹是否存在 |
getAbsoluteFile() | File | 返回抽象路径名的绝对路径名形式 |
getAbsolutePath() | String | 获取文件的绝对路径 |
getName() | String | 获取文件或文件夹的名称 |
getParent() | String | 获取文件的父路径 |
getPath() | String | 获取路径名字符串 |
getFreeSpace() | long | 返回此抽象路径名指定的分区中未分配的字符节数 |
getTotalSpace() | long | 返回此抽象路径名指定的分区大小 |
length() | long | 获取文件的长度(以字节为单位) |
isFile() | boolean | 判断是不是文件 |
isHidden() | boolean | 判断文件是否是隐藏文件 |
lastModified() | long | 获取文件最后修改时间 |
renameTo(File dest) | boolean | 重新命名文件 |
setLastModified(long time) | boolean | 设置文件或文件夹的最后一次修改时间 |
setReadOnly() | boolean | 将文件或文件夹设置为只读 |
toURI | URI | 构造一个表示此抽象路径名的file.URI |
代码实现:
public classFileTest {
publicstatic void main(String[] args) {
Filefile = new File("test.txt"); // 创建文件对象
if(!file.exists()) { // 文件不存在(程序第一次运行时,执行的语句块)
System.out.println("未在指定目录下找到文件名为“test”的文本文件!正在创建...");
try{
file.createNewFile();
}catch (IOException e) {
e.printStackTrace();
}// 创建该文件
System.out.println("文件创建成功!");
}else { // 文件存在(程序第二次运行时,执行的语句块)
System.out.println("找到文件名为“test”的文本文件!");
if(file.isFile() && file.canRead()) { // 该文件文件是一个标准文件且该文件可读
System.out.println("文件可读!正在读取文件信息...");
StringfileName = file.getName(); // 获得文件名
StringfilePath = file.getAbsolutePath(); // 获得该文件的绝对路径
booleanhidden = file.isHidden(); // 获得该文件是否被隐藏
longlen = file.length(); // 获取该文件中的字节数
longtempTime = file.lastModified(); // 获取该文件最后的修改时间
SimpleDateFormatsdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); // 创建SimpleDateFormat对象,指定目标格式
Datedate = new Date(tempTime); // 使用“文件最后修改时间”创建Date对象
Stringtime = sdf.format(date); // 格式化“文件最后的修改时间”
System.out.println("文件名:" +fileName); // 输出文件名
System.out.println("文件的绝对路径:"+ filePath); // 输出文件的绝对路径
System.out.println("文件是否是隐藏文件:"+ hidden); // 输出文件是否被隐藏
System.out.println("文件中的字节数:"+ len); // 输出该文件中的字节数
System.out.println("文件最后的修改时间:"+ time); // 输出该文件最后的修改时间
file.delete();// 查完该文件信息后,删除文件
System.out.println("这个文件的使命结束了!已经被删除了。");
}else { // 文件不可读
System.out.println("文件不可读!");
}
}
}
}
第一次运行:
未在指定目录下找到文件名为“test”的文本文件!正在创建...
文件创建成功!
第二次运行:
找到文件名为“test”的文本文件!
文件可读!正在读取文件信息...
文件名:test.txt
文件的绝对路径:D:\Eclipse\HelloJava\test.txt
文件是否是隐藏文件:false
文件中的字节数:0
文件最后的修改时间:2018/07/07 21:15:33
这个文件的使命结束了!已经被删除了。
3.3文件夹操作
File类中对文件夹进行操作的常用方法 | ||
方法 | 返回值 | 说明 |
isDirectory() | boolean | 判断是不是文件夹 |
list() | String[] | 返回字符串数组,这些字符串指定此抽象路径明表示的目录中的文件和目录 |
list(FileFilter filter) | String[] | 返回字符串数组,这些字符串指定此抽象路径明表示的目录中满足指定过滤器的文件和目录 |
listFiles() | File[] | 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件 |
listFiles(FileFilter filter) | File[] | 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录 |
mkdir() | boolean | 创建此抽象路径名指定的目录 |
mkdirs() | boolean | 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录 |
代码实现:
public classFolderTest {
publicstatic void main(String[] args) {
Stringpath = "D:\\Test"; // 声明文件夹Test所在的目录
for(int i = 1; i <= 10; i++) { // 循环获得i值,并用i命名新的文件夹
Filefolder = new File(path + "\\" + i); // 根据新的目录创建File对象
if(!folder.exists()) { // 文件夹不存在
folder.mkdirs();//创建新的文件夹(包括不存在的父文件夹)
}
}
System.out.println("文件夹创建成功,请打开D盘查看!\n\nC盘文件及文件夹列表如下:");
Filefile = new File("C:\\"); // 根据路径名创建File对象
File[]files = file.listFiles(); // 获得C盘的所有文件和文件夹
for(File folder : files) { // 遍历files数组
if(folder.isFile())// 判断是否为文件
System.out.println(folder.getName()+ " 文件"); // 输出C盘下所有文件的名称
elseif (folder.isDirectory())// 判断是否为文件夹
System.out.println(folder.getName()+ " 文件夹"); // 输出C盘下所有文件夹的名称
}
}
}
结果:
文件夹创建成功,请打开D盘查看!
C盘文件及文件夹列表如下:
$Recycle.Bin文件夹
$Windows.~WS文件夹
61eb5d30b9394a8cf1e7文件夹
……
(4)文件输入/输出流
4.1FileInputStream类与FileOutputStream类
FileInputStream类常用方法与InputStream类相同;FileOutputStream类常用方法与OutputStream类相同。
代码实现:
public classFileStreamTest {
publicstatic void main(String[] args) {
Filefile = new File("word.txt"); // 创建文件对象
try{ // 捕捉异常
//创建FileOutputStream对象,用来向文件中写入数据
FileOutputStreamout = new FileOutputStream(file);
Stringcontent = "你见过洛杉矶凌晨4点的样子吗?"; // 定义字符串,用来存储要写入文件的内容
//创建byte型数组,将要写入文件的内容转换为字节数组
bytebuy[] = content.getBytes();
out.write(buy);// 将数组中的信息写入到文件中
out.close();// 将流关闭
}catch (IOException e) { // catch语句处理异常信息
e.printStackTrace();// 输出异常信息
}
try{
//创建FileInputStream对象,用来读取文件内容
FileInputStreamin = new FileInputStream(file);
bytebyt[] = new byte[1024]; // 创建byte数组,用来存储读取到的内容
intlen = in.read(byt); // 从文件中读取信息,并存入字节数组中
//将文件中的信息输出
System.out.println("文件中的信息是:"+ new String(byt, 0, len));
in.close();// 关闭流
}catch (Exception e) {
e.printStackTrace();
}
}
}
结果:文件中的信息是:你见过洛杉矶凌晨4点的样子吗?
4.2FileReader类与FileWriter类
代码实现:
public classReaderAndWriter {
publicstatic void main(String[] args) {
while(true) { // 设置无限循环,实现控制台的多次输入
try{
Filefile = new File("word.txt"); // 在当前目录下创建名为“word.txt”的文本文件
if(!file.exists()) { // 如果文件不存在时,创建新的文件
file.createNewFile();
}
System.out.println("请输入要执行的操作序号:(1.写入文件;2.读取文件)");
Scannersc = new Scanner(System.in); // 控制台输入
intchoice = sc.nextInt(); // 获得“要执行的操作序号”
switch(choice) { // 以“操作序号”为关键字的多分支语句
case1: // 控制台输入1
System.out.println("请输入要写入文件的内容:");
StringtempStr = sc.next(); // 获得控制台上要写入文件的内容
FileWriterfw = null; // 声明字符输出流
try{
fw= new FileWriter(file, true); // 创建可扩展的字符输出流,向文件中写入新数据时不覆盖已存在的数据
fw.write(tempStr+ "\r\n"); // 把控制台上的文本内容写入到“word.txt”中
}catch (IOException e) {
e.printStackTrace();
}finally {
fw.close();// 关闭字符输出流
}
System.out.println("上述内容已写入到文本文件中!");
break;
case2: // 控制台输入2
FileReaderfr = null; // 声明字符输入流
if(file.length() == 0) { // “word.txt”中的字符数为0时,控制台输出“文本中的字符数为0!!!”
System.out.println("文本中的字符数为0!!!");
}else { // “word.txt”中的字符数不为0时
try{
fr= new FileReader(file); // 创建用来读取“word.txt”中的字符输入流
char[]cbuf = new char[1024]; // 创建可容纳1024个字符的数组,用来储存读取的字符数的缓冲区
inthasread = -1; // 初始化已读取的字符数
while((hasread = fr.read(cbuf)) != -1) { // 循环读取“word.txt”中的数据
System.out.println("文件“word.txt”中的内容:\n"+ new String(cbuf, 0, hasread)); // 把char数组中的内容转换为String类型输出
}
}catch (IOException e) {
e.printStackTrace();
}finally {
fr.close();// 关闭字符输入流
}
}
break;
default:
System.out.println("请输入符合要求的有效数字!");
break;
}
}catch (InputMismatchException imexc) {
System.out.println("输入的文本格式不正确!请重新输入...");
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
结果:
请输入要执行的操作序号:(1.写入文件;2.读取文件)
2
文本中的字符数为0!!!
请输入要执行的操作序号:(1.写入文件;2.读取文件)
1
请输入要写入文件的内容:
我要也一定能学会java
上述内容已写入到文本文件中!
请输入要执行的操作序号:(1.写入文件;2.读取文件)
2
文件“word.txt”中的内容:
我要也一定能学会java
(5)带缓冲的输入/输出流
5.1BufferedInputStream类与BufferedOutputStream类
代码实现:
public classBufferedStreamTest {
publicstatic void main(String args[]) {
//定义字符串数组
Stringcontent[] = { "你不喜欢我,","我一点都不介意。","因为我活下来,","不是为了取悦你!" };
Filefile = new File("word.txt"); // 创建文件对象
FileOutputStreamfos = null; // 创建FileOutputStream对象
BufferedOutputStreambos = null; // 创建BufferedOutputStream对象
FileInputStreamfis = null; // 创建FileInputStream对象
BufferedInputStreambis = null;// 创建BufferedInputStream对象
try{
fos= new FileOutputStream(file); // 实例化FileOutputStream对象
bos= new BufferedOutputStream(fos); // 实例化BufferedOutputStream对象
byte[]bContent = new byte[1024]; // 创建可以容纳1024个字节数的缓冲区
for(int k = 0; k < content.length; k++) { // 循环遍历数组
bContent= content[k].getBytes();// 将遍历到的数组内容转换为字节数组
bos.write(bContent);//将字节数组内容写入文件
}
System.out.println("写入成功!\n");
}catch (IOException e) { // 处理异常
e.printStackTrace();
}finally {
try{
bos.close();//将BufferedOutputStream流关闭
fos.close();//将FileOutputStream流关闭
}catch (IOException e) {
e.printStackTrace();
}
}
try{
fis= new FileInputStream(file); // 实例化FileInputStream对象
bis= new BufferedInputStream(fis);// 实例化BufferedInputStream对象
byte[]bContent = new byte[1024];// 创建byte数组,用来存储读取到的内容
intlen = bis.read(bContent); // 从文件中读取信息,并存入字节数组中
System.out.println("文件中的信息是:"+ new String(bContent, 0, len)); // 输出文件数据
}catch (IOException e) { // 处理异常
e.printStackTrace();
}finally {
try{
bis.close();//将BufferedInputStream流关闭
fis.close();//将FileInputStream流关闭
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
结果:
写入成功!
文件中的信息是:你不喜欢我,我一点都不介意。因为我活下来,不是为了取悦你!
5.2BufferedReader类与BufferedWriter类--分别继承Reader类和Writer类,这两个类同样具有内部缓冲机制,并可以以行为单位进行输入输出。
BufferedReader类常用方法 | ||
方法 | 返回值 | 说明 |
read() | int | 读取单个字符 |
readLine() | String | 读取一个文本行,并将其返回为字符串,若无数据可读,则返回null |
BufferedWriter类常用方法 | ||
write(String s,int off,int len) | void | 写入字符串的某一部分 |
fiush() | void | 刷新该流的缓冲 |
newLine() | void | 写出一个行分割符 |
代码实现:
public classStudent {
publicstatic void main(String args[]) {
//定义字符串数组
Stringcontent[] = { "你不喜欢我,","我一点都不介意。","因为我活下来,","不是为了取悦你!" };
Filefile = new File("word.txt"); // 创建文件对象
try{
FileWriterfw = new FileWriter(file); // 创建FileWriter类对象
//创建BufferedWriter类对象
BufferedWriterbufw = new BufferedWriter(fw);
for(int k = 0; k < content.length; k++) { // 循环遍历数组
bufw.write(content[k]);// 将字符串数组中元素写入到磁盘文件中
bufw.newLine();// 将数组中的单个元素以单行的形式写入文件
}
bufw.close();// 将BufferedWriter流关闭
fw.close();// 将FileWriter流关闭
}catch (IOException e) { // 处理异常
e.printStackTrace();
}
try{
FileReaderfr = new FileReader(file); // 创建FileReader类对象
//创建BufferedReader类对象
BufferedReaderbufr = new BufferedReader(fr);
Strings = null; // 创建字符串对象
inti = 0; // 声明int型变量
//如果文件的文本行数不为null,则进入循环
while((s = bufr.readLine()) != null) {
i++;// 将变量做自增运算
System.out.println("第" + i +"行:" + s); // 输出文件数据
}
bufr.close();// 将BufferedReader 流关闭
fr.close();// 将FileReader流关闭
}catch (IOException e) { // 处理异常
e.printStackTrace();
}
}
}
结果:
第1行:你不喜欢我,
第2行:我一点都不介意。
第3行:因为我活下来,
第4行:不是为了取悦你!
(6)数据输入/输出流
DateOutputStream类常用方法 | ||
方法 | 返回值 | 说明 |
size() | int | 返回计数器written的当前值,即到目前为止写入此数据输出流的字节数 |
write(byte[]b,int off,int len) | void | 将指定的byte数组中从偏移量off开始的len个字节写入基础输出流 |
write(int b) | void | 将指定字节写入基础流中 |
writeBoolean(boolean v) | void | 将一个boolean值以1-byte值的形式写入基础流中 |
writeByte(int v) | void | 将一个byte值以1-byte值的形式写入基础流中 |
writeBytes(String s) | void | 将字符串按照字节顺序写入基础输出流中 |
writeChar(int v) | void | 将一个char值以2-byte值的形式写入基础流中,先写入高字节 |
writeChars(String s) | void | 将字符串按照字符顺序写入基础输出流 |
writeDouble(double v) | void | 使用double类的doubleToLongBits方法将double参数转换为一个long值,然后将该long值以8-byte值的形式写入基础流中,先写入高字节 |
writeFloat(float v) | void | 使用Float类的floatToLongBits方法将float参数转换为一个int值,然后将该int值以4-byte值的形式写入基础流中,先写入高字节 |
writeInt(int v) | void | 将一个int值以4-byte值的形式写入基础流中,先写入高字节 |
writeLong(long v) | void | 将一个long值以8-byte值的形式写入基础流中,先写入高字节 |
writeShort(int v) | void | 将一个short值以2-byte值的形式写入基础流中,先写入高字节 |
writeUTF(String str) | void | 使用UTF-8编码将一个字符串写入基础输出流中 |
代码实现
public classExample_Data {
publicstatic void main(String[] args) {
try{
//创建FileOutputStream对象,指定要向其中写入数据的文件
FileOutputStreamfs = new FileOutputStream("word.txt");
//创建DataOutputStream对象,用来向文件中写入数据
DataOutputStreamds = new DataOutputStream(fs);
ds.writeUTF("使用writeUTF()方法写入数据");// 将字符串写入文件
ds.writeDouble(19.8);//将double数据写入文件
ds.writeInt(298);//将int数据写入文件
ds.writeBoolean(true);//将boolean数据写入文件
ds.close();// 关闭写入流
//创建FileInputStream对象,指定要从中读取数据的文件
FileInputStreamfis = new FileInputStream("word.txt");
//创建DataInputStream对象,用来从文件中读取文件
DataInputStreamdis = new DataInputStream(fis);
System.out.println("readUTF方法读取数据:"+ dis.readUTF()); // 读取字符串
System.out.println("readDouble方法读取数据:"+ dis.readDouble()); // 读取double数据
System.out.println("readInt方法读取数据:"+ dis.readInt()); // 读取int数据
System.out.println("readBoolean方法读取数据:"+ dis.readBoolean()); // 读取boolean数据
}catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
readUTF方法读取数据:使用writeUTF()方法写入数据
readDouble方法读取数据:19.8
readInt方法读取数据:298
readBoolean方法读取数据:true
两种关闭流的方法:
1)使用close()显式关闭
2)使用try语句自动关闭
12.反射
(1)Class类与Java反射
1.1Class类—创建Class类对象的3种方法
1)实用类的class属性
Class c=Demo.class
2)使用Class类的forName方法
try{
Class c=Class.forName(“test.demo”)
}catch(ClassNotFoundException el){
el.printStackTrace();
}
3)使用Object对象的getClass方法
Demodemo=new Demo();
Class c=demo.getClass();
1.2获取构造方法
代码实现:
该类提供构造方法
public classGetConstructorTest {
Strings;// 定义一个字符串变量
inti, i2, i3;// 定义3个int变量
privateGetConstructorTest() {// 无参构造函数
}
protectedGetConstructorTest(String s, int i) {// 有参构造函数,用来为字符串变量和int变量初始化值
this.s= s;
this.i= i;
}
publicGetConstructorTest(String... strings) throws NumberFormatException {
if(strings.length > 0)// 如果字符串长度大于0
i= Integer.valueOf(strings[0]);// 将字符串的第1个字符串赋值给变量i
if(strings.length > 1)// 如果字符串长度大于1
i2= Integer.valueOf(strings[1]);// 将字符串的第2个字符串赋值给变量i2
if(strings.length > 2)// 如果字符串长度大于2
i3= Integer.valueOf(strings[2]);// 将字符串的第3个字符串赋值给变量i3
}
publicvoid print() {
//输出成员变量的值
System.out.println("s="+ s);
System.out.println("i="+ i);
System.out.println("i2="+ i2);
System.out.println("i3="+ i3);
}
}
测试类获取所有构造方法
public classGetConstructorMain {
publicstatic void main(String[] args) {
GetConstructorTestexample = new GetConstructorTest("10", "20","30");
Class<?extends GetConstructorTest> exampleC = example.getClass();
// 获得所有构造方法
Constructor[]declaredConstructors = exampleC.getDeclaredConstructors();
for(int i = 0; i < declaredConstructors.length; i++) {// 遍历构造方法
Constructor<?>constructor = declaredConstructors[i];
System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
System.out.println("该构造方法的入口参数类型依次为:");
Class[]parameterTypes = constructor.getParameterTypes();// 获取所有参数类型
for(int j = 0; j < parameterTypes.length; j++) {
System.out.println("" + parameterTypes[j]);
}
System.out.println("该构造方法可能抛出的异常类型为:");
//获得所有可能抛出的异常信息类型
Class[]exceptionTypes = constructor.getExceptionTypes();
for(int j = 0; j < exceptionTypes.length; j++) {
System.out.println("" + exceptionTypes[j]);
}
GetConstructorTestexample2 = null;
while(example2 == null) {
try{// 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
if(i == 2)// 通过执行默认没有参数的构造方法创建对象
example2= (GetConstructorTest) constructor.newInstance();
elseif (i == 1)
//通过执行具有两个参数的构造方法创建对象
example2= (GetConstructorTest) constructor.newInstance("7", 5);
else{// 通过执行具有可变数量参数的构造方法创建对象
Object[]parameters = new Object[] { new String[] { "100","200", "300" } };
example2= (GetConstructorTest) constructor.newInstance(parameters);
}
} catch (Exception e) {
System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
constructor.setAccessible(true);//设置为允许访问
}
}
if(example2 != null) {
example2.print();
System.out.println();
}
}
}
}
运行结果:
查看是否允许带有可变数量的参数:true
该构造方法的入口参数类型依次为:
class [Ljava.lang.String;
该构造方法可能抛出的异常类型为:
class java.lang.NumberFormatException
s=null
i=100
i2=200
i3=300
访问GetConstructorTest(String... strings)输出的信息
查看是否允许带有可变数量的参数:false
该构造方法的入口参数类型依次为:
class java.lang.String
int
该构造方法可能抛出的异常类型为:
s=7
i=5
i2=0
i3=0
访问GetConstructorTest(String s, int i)输出的信息
查看是否允许带有可变数量的参数:false
该构造方法的入口参数类型依次为:
该构造方法可能抛出的异常类型为:
在创建对象时抛出异常,下面执行setAccessible()方法
s=null
i=0
i2=0
i3=0
访问GetConstructorTest()输出的信息
1.3获取成员变量
代码实现
创建一个类、声明变量
public classGetFieldTest {
inti;// 定义int类型成员变量
publicfloat f;// 定义float类型成员变量
protectedboolean b;// 定义boolean类型成员变量
privateString s;// 定义私有的String类型成员变量
}
创建测试类
importjava.lang.reflect.*;
public classGetFieldMain {
publicstatic void main(String[] args) {
GetFieldTestexample = new GetFieldTest();
ClassexampleC = example.getClass();
//获得所有成员变量
Field[]declaredFields = exampleC.getDeclaredFields();
for(int i = 0; i < declaredFields.length; i++) {
Fieldfield = declaredFields[i]; // 遍历成员变量
//获得成员变量名称
System.out.println("名称为:" +field.getName());
ClassfieldType = field.getType(); // 获得成员变量类型
System.out.println("类型为:" +fieldType);
booleanisTurn = true;
while(isTurn) {
//如果该成员变量的访问权限为private,则抛出异常,即不允许访问
try{
isTurn= false;
//获得成员变量值
System.out.println("修改前的值为:"+ field.get(example));
//判断成员变量的类型是否为int型
if(fieldType.equals(int.class)) {
System.out.println("利用方法setInt()修改成员变量的值");
field.setInt(example,168); // 为int型成员变量赋值
//判断成员变量的类型是否为float型
} else if(fieldType.equals(float.class)) {
System.out.println("利用方法setFloat()修改成员变量的值");
//为float型成员变量赋值
field.setFloat(example,99.9F);
//判断成员变量的类型是否为boolean型
}else if (fieldType.equals(boolean.class)) {
System.out.println("利用方法setBoolean()修改成员变量的值");
//为boolean型成员变量赋值
field.setBoolean(example,true);
}else {
System.out.println("利用方法set()修改成员变量的值");
//可以为各种类型的成员变量赋值
field.set(example,"MWQ");
}
//获得成员变量值
System.out.println("修改后的值为:"+ field.get(example));
}catch (Exception e) {
System.out.println("在设置成员变量值时抛出异常,"
+"下面执行setAccessible()方法!");
field.setAccessible(true);// 设置为允许访问
isTurn= true;
}
}
System.out.println();
}
}
}
运行结果:
名称为:i
类型为:int
修改前的值为:0
利用方法setInt()修改成员变量的值
修改后的值为:168
名称为:f
类型为:float
修改前的值为:0.0
利用方法setFloat()修改成员变量的值
修改后的值为:99.9
名称为:b
类型为:boolean
修改前的值为:false
利用方法setBoolean()修改成员变量的值
修改后的值为:true
名称为:s
类型为:class java.lang.String
在设置成员变量值时抛出异常,下面执行setAccessible()方法!
修改前的值为:null
利用方法set()修改成员变量的值
修改后的值为:MWQ
1.4获取方法
代码实现:
创建一个类编写方法
public class GetMehodTest {
static void staticMethod() {//定义静态方法,用于测试,无实际意义
System.out.println("执行staticMethod()方法");
}
public int publicMethod(inti) {//定义共有方法,用于测试,无实际意义
System.out.println("执行publicMethod()方法");
return i * 100;
}
protected intprotectedMethod(String s, int i)//定义保护方法,用于测试,无实际意义
throws NumberFormatException {
System.out.println("执行protectedMethod()方法");
return Integer.valueOf(s)+ i;
}
private String privateMethod(String...strings) {//定义私有方法,用于测试,无实际意义
System.out.println("执行privateMethod()方法");
StringBuffer stringBuffer = newStringBuffer();
for (int i = 0; i <strings.length; i++) {
stringBuffer.append(strings[i]);
}
return stringBuffer.toString();
}
}
创建测试类,获取所有方法
public classGetMehodMain {
publicstatic void main(String[] args) {
GetMehodTestexample = new GetMehodTest();
ClassexampleC = example.getClass();
//获得所有方法
Method[]declaredMethods = exampleC.getDeclaredMethods();
for (int i = 0; i <declaredMethods.length; i++) {
Methodmethod = declaredMethods[i]; // 遍历方法
System.out.println("名称为:" +method.getName()); // 获得方法名称
System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
System.out.println("入口参数类型依次为:");
//获得所有参数类型
Class[]parameterTypes = method.getParameterTypes();
for(int j = 0; j < parameterTypes.length; j++) {
System.out.println("" + parameterTypes[j]);
}
//获得方法返回值类型
System.out.println("返回值类型为:"+ method.getReturnType());
System.out.println("可能抛出的异常类型有:");
//获得方法可能抛出的所有异常类型
Class[]exceptionTypes = method.getExceptionTypes();
for(int j = 0; j < exceptionTypes.length; j++) {
System.out.println("" + exceptionTypes[j]);
}
booleanisTurn = true;
while(isTurn) {
//如果该方法的访问权限为private,则抛出异常,即不允许访问
try{
isTurn= false;
if("staticMethod".equals(method.getName()))
method.invoke(example);// 执行没有入口参数的方法
elseif("publicMethod".equals(method.getName()))
System.out.println("返回值为:"
+method.invoke(example, 168)); // 执行方法
elseif("protectedMethod".equals(method.getName()))
System.out.println("返回值为:"
+method.invoke(example, "7", 5)); // 执行方法
elseif("privateMethod".equals(method.getName())) {
Object[] parameters = newObject[] { new String[] {
"M","W", "Q" } }; // 定义二维数组
System.out.println("返回值为:"
+method.invoke(example, parameters));
}
}catch (Exception e) {
System.out.println("在执行方法时抛出异常,"
+"下面执行setAccessible()方法!");
method.setAccessible(true);// 设置为允许访问
isTurn= true;
}
}
System.out.println();
}
}
}
运行结果:
名称为:publicMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
int
返回值类型为:int
可能抛出的异常类型有:
执行publicMethod()方法
返回值为:16800
名称为:privateMethod
是否允许带有可变数量的参数:true
入口参数类型依次为:
class [Ljava.lang.String;
返回值类型为:class java.lang.String
可能抛出的异常类型有:
在执行方法时抛出异常,下面执行setAccessible()方法!
执行privateMethod()方法
返回值为:MWQ
名称为:staticMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
返回值类型为:void
可能抛出的异常类型有:
执行staticMethod()方法
名称为:protectedMethod
是否允许带有可变数量的参数:false
入口参数类型依次为:
class java.lang.String
int
返回值类型为:int
可能抛出的异常类型有:
class java.lang.NumberFormatException
执行protectedMethod()方法
返回值为:12
(2)Annotation注解
2.1内置注解
2.2自定义注解
1)自定义注解
2)使用元注解对自定义注解进行设置
代码实现:
@Target(ElementType.FIELD) //注解用于成员属性
@Retention(RetentionPolicy.RUNTIME)// 在运行时保留(即运行时保留)
public @interfacePhoneAnnotation { // 创建一个名为“手机信息”的注解
publicString remarks() default "";// 备注,默认值为空白字符串
publicboolean enable() default true;// 是否启用,默认值为true,即启用
}
3)反射注解
代码实现:
创建一个类进行注释
public classCellphone { // 创建“手机”类
@PhoneAnnotation(remarks= "品牌型号")
publicString brdMdl;// 属性注释中的备注值为“品牌型号”,是否启用值为默认值
@PhoneAnnotation(remarks= "价格")
publicdouble price;// 属性注释中的备注值为“价格”,是否启用值为默认值
@Deprecated// 将此属性设为过时
@PhoneAnnotation(remarks= "电池接口", enable = false)
publicString batteryInter;// 属性注释中的备注值为“电池接口”,是否启用值为不启用
@PhoneAnnotation(remarks= "手机厂商")
StringproducedArea;// 属性注释中的备注值为“手机厂商”,是否启用值为默认值
}
创建一个测试类获取注解信息
public classTest { // 创建测试类
publicstatic void main(String[] args) {
Class<Cellphone>c = Cellphone.class;// 创建反射对象
Field[]fields = c.getDeclaredFields(); // 通过Java反射机制获得类中的所有属性
for(Field field : fields) { // 遍历属性数组
//判断Cellphone类中是否具有PhoneAnnotation类型的注解
if(field.isAnnotationPresent(PhoneAnnotation.class)) {
//获取指定类型的注解
PhoneAnnotationphoneAnnotation = field.getAnnotation(PhoneAnnotation.class); // 输出成员变量注解中的所有内容
System.out.println(field.getName() + "属性注解:备注=" + phoneAnnotation.remarks()+ ",是否有效=" + phoneAnnotation.enable());
}
}
}
}
运行结果:
brdMdl属性注解:备注=品牌型号,是否有效=true
price属性注解:备注=价格,是否有效=true
batteryInter属性注解:备注=电池接口,是否有效=false
producedArea属性注解:备注=手机厂商,是否有效=true