JavaSE笔记
Java SE笔记
remove和delete两个方法的区别
- delete是物理删除(将存储的数据直接抹掉);remove的话包含逻辑删除。(逻辑上删除了数据变成了垃圾数据,但实际上该数据还是保留在存储器上)
修饰符
权限修饰符
修饰符 | 同一个类中 | 同一个包中子类、无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
状态修饰符
final(最终)
修饰方法
- 表示该方法是最终方法,不能被重写。
修饰变量
-
基本型变量
表示该变量是常量,不能再次被赋值。 -
引用型变量
表示该引用类型变量的地址值不能发生改变(该变量不能指向其它引用对象),但是地址里的内容可以发生改变(所指对象的属性状态可以发送改变)。
修饰类
- 表示该类是最终类,不能被继承。
static(静态)
- 被该类的所有对象共享,这也是我们判断是否使用static的条件
一般使用静态变量时,首先在主方法main内初始化定义静态变量值。 - 范例:
类名 . 静态变量名 = 初始化值;
调用方式
-
使用类名调用(推荐):
类名 . 静态变量名 = 初始化值; -
使用对象名调用 :
对象名 . 静态变量名 = 值;
static访问特点
-
非静态的成员方法
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
-
静态的成员方法
- 只能访问静态的成员方法/变量
字符串
String
- JAVA程序中所有的双引号字符串,都是String类的对象
String的特点
- 字符串不可变,他们的值在创建后不能被更改。
- 虽然String的值是不可变的,但是它们可以被共享(被其它变量引用)。
- 字符串效果上相当于字符数组(char[]),但是底层原理是字节数组(byte[])。
String构造方法
-
public String()
创建一个空白字符串对象,不含有任何内容。 -
public String(char[] chs)
根据字符数组的内容,来创建字符串对象。 -
public String(byte bys)
根据字节数组的内容(根据ASCII码输出对应的字符),来创建字符串对象。 -
String s = "abc"
直接赋值的方式创建字符串对象,内容就是abc建议使用该方式直接赋值创建字符串。
String对象的特点
-
通个new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同。
char[] chs = {‘a’, 'b', 'c'}; String s1 = new String(chs); String s2 = new String(chs);
-
以“”方式创建的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM只建立一个String对象
//s3,s4的地址值相同 String s3 = "abc"; String s4 = "abc";
String的比较
-
使用 == 做比较
- 基本类型:比较的是数据值是否相同基本类型int boolean char等。
- 引用类型:比较的是地址值是否相同引用类型String。
-
使用 equals()做比较
- public boolean equals(Object anObject)
- 比较的是String字符串的内容,不是地址。
String的遍历
- 字符串.charAt(下标索引)
通过该方法返回指定索引处的char值,字符串的索引也是从0开始的。 - 字符串.length()
返回该字符串的长度,数组长度:数组名.length(数组长度调用的是数组对象的属性值,不是方法)。
StringBuilder
StringBuilder概述
StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是StringBuilder对象中的内
容是可变的。
String 和 StringBuilder的区别
- String:内容不可变的
- StringBuilder:内容是可变的
StringBuilder构造方法
- public StringBuilder()
创建一个空白可变字符串对象,不含有任何内容 - public String Builder(String str)
根据字符串的内容,来创建可变字符串对象 - 正常创建一个StringBuilder字符串容器:StringBuilder s1 = new StringBuilder();
StringBuilder的添加反转
- public StringBuilder append(任意类型)
添加数据,并返回对象本身 - public StringBuilder reverse()
返回相反的字符串序列
StringBuilder和String的转换
-
StringBuilder转换成String
public String toString():通过toString()就可以实现StringBuilder转换成String。 -
String转换成StringBuilder
public StringBuilder(String str):通过构造方法就可以实现String转换成StringBuilder。
内部类
概述:在一个类中定义一个类
举例:在类A中定义一个类B,类B就被称为内部类
//格式:
public class 类名{
修饰符 class 类名{
}
}
访问特点
- 内部类可以直接访问外部类的成员 ( 包括私有 )。
- 外部类要访问内部类的成员,必须创建对象。
成员/局部内部类
在类的成员位置:成员内部类
- 外界创建对象使用方法
//格式:
外部类名.内部类名 对象名 = new 外部类对象. new 内部类对象;
//范例:
Outer.Inner oi = new Outer().new Inner();
在类的局部位置:局部内部类
- 匿名内部类(方法里的内部类)
- 前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
- 本质:是一个继承了该类或者实现了该接口的子类匿名对象
格式:
new 类名/接口名(){
重写方法;
};
范例:
new Inter(){
public void show(){
}
}
多态
-
概述:同一个对象,在不同时刻表现出来的不同形态
-
前提:有继承/实现关系,有方法重写,有父(类/接口)引用指向(子/实现)类对象。
成员访问特点
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
- 为什么成员变量/方法的访问不一样哪?
- 成员方法有重写,成员变量没有
好处和弊端
- 好处:提高了程序的扩展性
- 弊端:不能使用子类的特有功能
多态中的转型
-
向上转型(从子到父)
父类引用指向子类对象//对象c可以调用Cat中重写的成员方法,不能用Cat中特有的成员方法。 Animal c = new Cat();//可能会丢失部分数据
-
向下转型(从父到子)
父类引用转为子类对象//将c强制转换成Cat引用类型,赋值给Cat型 的a对象;a就可以访问Cat中的特有方法了。 Animal c = new cat( ); Cat a = (Cat)c;//可能会报错
抽象类名作形参和返回值
方法的形参是抽象类名,其实需要的是该抽象类的子类对象
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
抽象类
概述:在java中,一个没有方法体(方法后没有大括号及内容直接以分号结尾)的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类抽象方法必须在抽象类中.
抽象类的特点
//关键字:abstract
//范例:
public abstract class Animal{
public abstract void eat( );
}
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类不能创建对象,但可以参照多态的方式,通过子类创建对象实例化,叫做抽象类多态
-
抽象类的子类
- 要么重写父类(抽象类)的所有抽象方法
- 要么该子类也是一个抽象类
接口
概述:接口就是一种公共的规范标准,只要符合规范标准,大家都可以用,java中的接口更多的体现在对行为的抽象
接口的特点
//用关键字interface修饰
public interface 接口名{
program...
}
//类实现接口用implements表示
public class 类名 implements 接口名{
program...
}
- 接口不能实例化(创建对象)如果创建对象:参照多态的方法,这叫接口多态
- 接口的实现类
- 要么重写接口中的所有抽象方法
- 要么是抽象类
接口特性
-
接口中的
方法
:默认为 公共抽象方法( public abstract,只能是 public abstract,其他修饰符都会报错)。 -
接口中的
变量
:默认为 公共静态常量public static final
(只能是 public static final,其他修饰符都会报错)。 -
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
接口与类的区别
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法(Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法)。
- 接口不能包含成员变量(除了 public static final 公共静态常量)。
- 接口不是被类继承,而是被类实现。
- 接口支持多继承(一个类可以实现多个接口)。
抽象类和接口的区别
-
抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
-
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
-
接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
一个类只能继承一个抽象类,而一个类却可以实现多个接口。
-
设计理念区别
-
抽象类:对类抽象,包括属性、行为
-
接口:对行为抽象,主要是行为
-
接口的组成更新
默认方法(java8)
//关键字default
//格式:
public default 返回值类型 方法名(参数列表){ }
//范例:
public default void show3( ){ }
接口中默认方法的注意事项
-
默认方法不是抽象方法,故不强制被重写;但是可以被重写,重写的时候去掉default关键字即可。
-
public可以省略,default不能省略。
-
作用:该接口默认方法主要是用来升级/更新,接口中的抽象方法的。避免向接口中添加新方法时,须向所有实现该接口的实现类重写该方法。
静态方法(java8)
//关键字:static
//格式:
public static 返回值类型 方法名(形参){ }
//范例:
public static void show( ){
System.out.println("静态方法");
}
接口中静态方法的注意事项
- 静态方法只能通过接口名调用,不能通过实现类名或对象名调用
- public可以省略,static不能省略
私有方法(java9)
- 当两个默认方法或静态方法,中包含一段相同的代码,就可以将其抽取出来,创建一个该接口私有的共性方法,供其在该接口中调用
//范例1:
private void show(){ }
//范例2:
private static void method(){ }
- 接口中私有方法的注意事项
- 默认方法可以调用私有的静态方法和非静态方法
- 静态方法只能调用私有的静态方法
常用API
- 没有构造方法,如何使用类中的成员哪?
- 看类的成员是否都是静态的成员 ? 如果是,可以通过类名直接调用。
工具类的设计思想
- 构造方法用private修饰
- 目的:封装,防止外部创建对象
- 成员用public static修饰
- 目的:便于使用类名访问方法
Math
- 不用导包,直接Math.xx()调用方法就行了
- Math类中的方法和常量都是静态的。
System
- System. Exit(0);为0值时,退出循环
- System.currentTimeMillis();当前距1970年的时间,以毫秒返回
Object
-
类object是类层次结构的根,每个类都有object作为超类。所有对象(包括数组)都实现了这个类的方法。
-
写标准类时
-
最好要重写Object的equals()方法
- 作用:比较两对象内容(所有属性)是否相同
- 默认(不重写):比较的是两对象地址是否相等
-
最好要重写Object的toString()方法
- 作用:以字符串的形式返回 对象 的所有属性
- 默认(不重写):返回值为 包名.类名@对象地址
-
Arrays
- 常用方法
- public static String Arrays.toString(int[ ] a)
数组转换成字符串 - public static String Arrays.deepToString(int[ ][ ] a)
- 二维数组转换成字符串
- public static void sort(int[ ] a)// 快排
数据大小排序,小-->大的顺序
- public static String Arrays.toString(int[ ] a)
SimpleDateFormat
-
格式化(从Date到String)
public final String format(Date date) -
解析(从String到Date)
public Date parse(String source) -
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
都是SimpleDateFormat下的方法,(先定义格式,后调用方法)
解析或格式化都需要有指定的样式
如"yyyy/MM/dd HH:mm:ss
"
基本类型包装类
基本数据类型 | 对应包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Integer
在lang包下,所有使用的时候不用导包
int型最小值:Integer . MIN_VALUE
int型最大值:Integer . MAX_VALUE
构造方法(已过时)
-
public Integer(int value);
-
根据int值创建Integer对象(已过时)
-
Integer i = new Integer(100);
-
public integer(String s);
-
根据String值创建Integer对象(已过时)
-
Integer i = new Integer("100")??""内输入的不是数字型字符串,会报错)
静态方法获取对象
-
public static Integer valueOf(int i);
-
返回表示指示的int值的Integer实例
-
Integer i = Integer.valueOf(100);
-
public static Integer valueOf(String s);
-
返回一个保存指定值的Integer对象String
-
Integer i = Integer.valueOf("100"); (""内输入的不是数字型字符串,会报错)
int和String的相互转换
- int转换String
String s2 = String.valueOf(number);
System.out.printfln(s2);
- String转换int
//方法一
String s = "100";
Integer i =Integer.valueOf(s);
int x = i.intValue();
System.out.printfln(x);
//方法二
int y = Integer.parseInt(s);
System.out.println(y);
//方法三
int i = Integer.valueOf(s);
System,out,println(i);
集合(Collections)
-
Collections
是一个包装类。它包含各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。 -
常用方法:
- Collections.sort(list)将集合升序排列
- sort(list, compartor)它可以添加比较器
- Collections.reverse(list)反转集合元素
- Collections.shuffle(list)随机进行排列洗牌操作
单列(Collection)
可重复(List列表)
LinkedList(双链表)
- 因为底层是链表,故适合增删改等操作。
ArrayList(数组)
-
可变的存储模型,存储的数据容量可以发生改变 (可调整大小的数组实现)。
-
:是某种数据类型(泛型)。 -
使用方法:在出现E的地方我们使用引用数据类型替代即可
举例:ArrayList, ArrayList
ArrayList构造方法和添加方法
- public ArrayList()
创建一个空的集合对象 - public Boolean add(E e)
将指定的元素追加到此集合的末尾 - public void add(int index,E element)
在该集合中的指定位置插入指定元素
ArrayList集合常用方法
- public boolean remove(Object o)
删除指定的元素,返回删除是否成功 - public E remove(int index)
删除指定索引处的元素,返回被删除的元素 - public E set(int index, E element)
修改指定索引处的元素,返回被修改的元素 - public E get(int index)
返回索引处的元素 - public int size()
返回集合中的元素的个数
不可重复(Set集合)
- Set集合特点
- 没有索引的方法,不可以使用普通的for循环遍历(可以使用for each循环遍历)
- 无重复元素的集合
TreeSet
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
无参构造方法:TreeSet()
- 根据元素的自然排序进行排序
- 自然排序,就是要引用类实现Comparable接口,重写compareTo()方法。
- 重写compareTo()方法,一定要注意排序规则必须按照要求的主要条件和次要条件来写
有参构造方法:TreeSet(Comparator comparator)
- 根据指定的比较器进行排序
- 带参的树型集合,是在new TreeSet<~>( )的括号里创建一个匿名的对象new Comparator<~>( ){ } ,然后在重写Comparator的compare()方法。
//给TreeSet<>()构造方法传入一个 匿名内部类
TreeSet students = new TreeSet(new Comparator() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() == o2.getAge()? 0:(o1.getAge() > o2.getAge()? 1:-1);
int num2 = num == 0 ? o1.getId().compareTo(o2.getId()) : num;
return num2;
}
});
HashSet
- 无法保证元素的存储和取出顺序是一致的
LikedHashSet
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的。
- 由哈希表保证元素唯一,也就是说没有重复的元素
迭代器(Iterator)
- 集合的专用遍历方法
- 迭代器是通过集合的iterator()方法得到的,故它是依赖于集合而存在的
- 增强for循环(for each)
- for(元素数据类型 变量名: 数组或Collection集合){}
双列(Map)
- Map集合概述
- Interface Map
K:键的类型;V:值的类型 - 键是唯一的,值是可重复的
- Interface Map
HashMap
-
HashMap的Hash是为了确定键(key)的唯一。
-
它的添加方法是.put()没有.add()方法。
TreeMap
-
通过构建比较器,指定排序方式。
-
有序的键值对集合排序方法与TreeSet一样。
泛型
- 将具体的类型参数化,然后在(使用/调用)时传入具体的类型
- 泛类定义格式:
- <类型>:指定一种类型的格式。
- <类型1,类型2...>:指定多种类型的格式,多种类型之间用逗号隔开。
- 这里的类型可以看成是形参。
泛型类
- 这里的
T
为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型. - 创建对象的时候再确定T的类型
Students1 = new Student ( );
定义格式:
修饰符class类名<类型>{ }
public class student{ }
泛型方法
定义格式:
修饰符 <类型> 返回值类型 方法名(类型 变量名){ }
public void show(T t){ }
泛型接口
定义格式:
修饰符 interface 接口名<类型>{ }
public interface Student{ }
类型通配符
-
类型通配符 <?>
- List<?>:表示元素类型未知的List,它的元素可以匹配任意的类型。
- 这种带通配符的List仅表示它是各种泛类List的父类,并不能把元素添加到其中
-
类型通配符上限<? extends类型>
- List<? extends Number>:它表示的类型是Number或者其子类型
-
类型通配符下限:<?super类型>
- List<?super Number>:它表示的类型是Number或者其父类型
可变参数
-
又称参数个数可变,用作方法的形参出现,使方法的形参个数是可变的
-
格式:修饰符 返回值类型 方法名(数据类型 . . . 变量名)
-
通过下面的可变参数声明,a就变成一个数组,可以通过【增强for循环】遍历
范例:
public static int show(int... a){ }
public static int show(String a, int...b){ }
IO流(输入/输出流)
- 功能:IO流就是用来处理设备间数据传输问题的
- 应用:文件的复制上传下载
- IO流分类:
- 按数据的流向
输入流:读数据
输出流:写数据 - 按数据类型(主要)
字节流:字节输入/流出
字符流:字符输入/流出
- 按数据的流向
File
File类:是文件和目录路径名的抽象表示
构造方法
//创建一个File类抽象对象,不会实质创建文件、文件夹
File(File parent, String child)
File f3 = new File("C:\\file3");
File f4 = new File(f3, "java.txt");
File(String parent, String child)
File f2 = new File("C:\\file2", "java.txt");
File(String pathname)
File f1 = new File("C:\\file1\\java.txt");
File类创建功能
- public boolean createNewFile()
当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。 - public boolean mkdir()
创建由此抽象路径名命名的目录。 - public boolean mkdirs()
创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。 (深层次的创建目录)
File类对象的常用方法
- boolean isDirectory()
测试此抽象路径名表示的文件是否为目录。 - boolean isFile()
测试此抽象路径名表示的文件是否为普通文件。 - String[] list()
返回一个字符串数组,元素为该抽象路径名目录下的所有文件和目录。 - File[] listFiles()
返回该抽象路径名表示的目录中所有文件和目录的File对象数组,File对象都是绝对路径。 - boolean exists()
测试此抽象路径名表示的文件或目录是否存在。 - String getAbsolutePath()
返回此抽象路径名的绝对形式。 - String getName()
返回由此抽象路径名表示的文件或目录的名称。 - String getPath()
将此抽象路径名转换为路径名字符串。 - public boolean delete()
删除由此抽象路径名表示的文件或目录。
如果一个目录中有内容(目录,文件),不能直接删除。应该先删除目录中的内容,最后才能删除目录。
递归
用来查找该目录下的所有文件:是目录递归调用,是文件打印绝对路径。
字节流
-
数据通过Windows自带的记事本打开,不能读懂里面的内容或不知道用那种类型的流,就用字节流(万能流)。
-
子类名称:子类名称都是以其父类名作为子类名的后缀的
字节流抽象基类
字节输入流(InputStream)
-
InputStream:该抽象类是表示字节输入流的所有类的超类。
-
FileInputStream类:通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名。
-
读写数据流标准代码
//创建字节输入流对象
FileInputStream fis = new FileInputStream(String name);
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream (String name);
int len;
byte[ ] bys = new byte[1024];
//读取数据;读取的字节数组为空时,fis.read(bys)返回-1
while((len=fis.read(bys)) != -1){
//写入到目标文件中
fos.write(bys, 0, len);
}
//释放资源
fis.close();
fos.close();
字节输出流(OutputStream)
OutputStream:这个抽象类是表示字节输出流的所有类的超类。
FileOutputStream类:文件输出流用于将文件写入File。
构造方法
//创建文件输出流以指定的名称写入文件
FileOutputStream(String name);
FileOutputStream(File file);
//创建对象
FileOutputStream fos = new FileOutputStream("idea_test\\src\\workspace\\fileDemo.txt");
//写入内容
fos.write(89);
//释放资源(很重要)
fos.close();
写入方法
-
fos.write(int b);向目标文件写入对应的int型数据。
-
fos.write(byte[ ] b);
字符串有个str.getBytes()方法,可以将字符串转换成byte数组。byte[ ] bys = "abcd".getBytes(); fos.write(bys); //三个参数分别是字节数组、偏移量(开始下标)、多少个字节(读取的元素个数) fos.write(byte[ ] b, int off, int len); //就是从bys数组下标为 1开始,读取 3 个字节写入目标文件中 fos.write(bys, 1, 3);
换行的实现
- 写完数据后,加换行符:
- Windows:\r\n
- Linux:\n
- mac:\r
追加写入的实现
- FileOutputStream(String name, boolean true);
- 创建fos对象的时候,在文件名后追加true,可以实现该功能。
文件写入的标准报错格式
//fos.close();一定要写在finally中
FileOutputStream fos = null;
try {
fos = new FileOutputStream("idea_test\\src\\workspace\\fileDemo.txt",true);
}catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节缓冲流
字节缓冲输入流
- BufferedInputStream类
- 构造方法:new BufferedInputStream(InputStream in);
- 创建一个内部缓冲区数组,一次可以读取很多字节。
字节缓冲输出流
-
BufferedOutputStream类
-
构造方法:new BufferedOutputStream(OutputStream out);
-
该类实现缓冲输出流;引用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
-
该字节缓冲输出流,调用write()方法,默认追加写入,不用在FileOutputStream()中加true。
字节缓冲流写入数据
//创建字节输出流
FileOutputStream fos = new FileOutputStream("idea_test\\src\\workspace\\fileDemo.txt");
//创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(fos);
//写入数据
bos. write("hello\r\n".getBytes());
bos. write("world\r\n".getBytes());
//释放数据
bos. close();
复制文件的四种方式
基本 一次读写一个字节
public static void fFun1(FileInputStream fis, FileOutputStream fos) throws IOException {
int by;
while ((by = fis. read()) != -1){
fos.write(by);
}
fis.close();fos.close();
}
基本 一次读写一个字节数组
public static void fFun2(FileInputStream fis, FileOutputStream fos) throws IOException {
int len;
byte[] bys = new byte[1024];
while ((len = fis. read(bys)) != -1){
fos.write(bys, 0, len);
}
fis.close();fos.close();
}
缓冲流 一次读写一个字节
public static void bFun1(BufferedInputStream bis, BufferedOutputStream bos) throws IOException {
int by;
while ((by = bis. read()) != -1){
bos. write(by);
}
bis. close();bos. close();
}
缓冲流 一次读写一个字节数组(最快)
public static void bFun2(BufferedInputStream bis, BufferedOutputStream bos) throws IOException {
int len;
byte[] bys = new byte[1024];
while ((len = bis. read(bys)) != -1){
bos. write(bys, 0, len);
}
bis. close();bos. close();
}
字符流
字符流 = 字节流 + 编码表
数据通过Windows自带的记事本打开,能读懂里面的内容
由于字节流操作中文不方便,所以Java就提供了字符流。
编码表
编码
- byte[ ] getBytes()
使用平台默认的字符集,将String编码为一系列字节。 - byte[ ] getBytes(String charsetName)
使用指定的字符集,将String编码为一系列字节。
解码
- new String(byte[ ] bytes)
通过平台默认的字符集,解码到指定的字节数组中,构造新的String。 - new String(byte[ ] bytes, String charsetName)
通过指定的字符集,解码到指定的字节数组中,构造新的String。
字符流抽象基类
字符输入流的抽象类(InputStreamReader)
字符流读数据的2种方法
-
int read()
一次读取一个字符数据 -
int read(char[ ] chs)
一次读取一个字符数组数据int len; char[] chars = new char[1024]; while ((len = isr.read(chars)) != -1){ System.out.println(new String(chars, 0, len)); }
FileReader(String filename)
//他两个是等价的
//为了简化InputStreamReader创建字符输入流对象的过程
InputStreamReader isr = new InputStreamReader(new FileInputStream(filename));
FileReader fileReader = new FileReader(filename);
字符输出流的抽象类(OutputStreamWriter)
字符流写数据的5种方法
写一个字符 | void write(int ch) |
---|---|
写入一个字符数组 | void write(char[ ] chs) |
写入字符数组的一部分 | void write(char[ ] chs, int off, int len) |
写一个字符串 | void write(String str) |
写一个字符串的一部分 | void write(String str, int off, int len) |
字符流的刷新
- 字符流写入数据后,要用osw.flush()刷新一下才会,数据才会在文件中显示。
//osw.close()是两步操作【先刷新,再释放资源】一旦关闭,就不能再写数据。
//【不释放写入流的资源,就无法读取】
osw.flush()
osw.close()
字符输出流的追加写入
FileWriter(String filename)
FileWrite(String filename, true);// true时,追加写入
字符缓冲流
-
输入流(BufferedReader)
-
构造方法:
BufferedWriter(Writer out) -
输出流(BufferedWriter)
-
构造方法:
BufferedReader(Reader in)
字符缓冲流特有功能
- public String readLine():读一行文字
- 它可以读取空格符,但读取不到换行符,如果读到流的结尾,侧为null。
String line;
while ((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
bw.fluh();
}
行分隔符
- void newLine():行分隔符由系统属性定义。
特殊操作流
System类
标准输入输出流
标准输入流
-
标准输入流:public static final InputStream in
-
自己实现键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); -
Java提供的键盘录入数据的类
Scanner sc = new Scanner(System.in);
in
- in就是一个字节输入流静态常量
- InputStream is = System.in
创建一个字节输入流对象
标准输出流
- 标准输出流:public static final PrintStream out
out
- out就是一个字节输出流静态常量
- PrintStream ps = System.out;
ps.println(); - 创建一个字节输出流对象(因为PrintStream是FilterOutputStream的子类,而FilterOutputStream又是OutputStream的子类;所以它也是一个字节输出流)调用该类的方法println(),打印括号内的内容。
打印流
字节打印流(PrintStream)
-
PrintStream ps = new PrintStream(String fileName);
创建指定文件名的字节打印流 -
使用write()方法写数据,查看的时候会转码;只用自己的特有方法println()等,查看的数据原样输出。
字符打印流(PrintWriter)
- 构造方法
- PrintWriter(String fileName)
创建一个PrintWriter对象,不会自动执行刷新。 - PrintWriter(Writer out, boolean autoFlush)
out:字符输出流。
autoFlush:如果为真侧println、printf、format方法将自动刷新输出缓冲流。
- PrintWriter(String fileName)
打印流特点
- 只负责输出数据,不负责读取数据
- 有自己的特有方法
对象序列化流
- 作用:将对象数据(状态)写入到磁盘文件中,使其可以长期保存,并且可以把保存的对象状态再读出来。
对象序列化流(ObjectOutputStream)
- 作用:存储对象信息
- 构造方法:
ObjectOutputStream(OutputStream out) - 序列化对象的方法:
void writeObject(Object obj)
将指定的对象写入ObjectOutputStream - 注意:
一个对象要想被序列化,该对象所属的类必须实现Serializable接口。
Serializable是一个标记接口,实现该接口,不需要重写任何方法。
对象反序列化流(ObjectInputStream)
- 作用:读取对象信息
- 构造方法:
ObjectInputStream(InputStream in) - 反序列化对象的方法:
void readObject( )
从ObjectOutputStream读取一个对象信息
三个问题
-
用对象序列化流序列化一个对象后,修改对象所属的类文件,后读取数据会报错
-
InvalidClassException
-
当序列化运行时检测到类中的以下问题之一时抛出。
- 类的串行版本与从流中读取的类描述符的类型不匹配
- 该类包含未知的数据类型
- 该类没有可访问的无参数构造函数
-
会出现【1】类问题,是因为序列化运行时将每个可序列化的类与称为serialVersionUID的版本号相关联。
-
解决上述问题
给对象所属的类加一个值:static final long serialVersionUID = 42L; -
如果一个对象中的某个成员变量的值不想被序列化,该怎么办?
给成员变量加上transient
关键字修饰,该关键字修饰的成员变量不参与序列化过程。(transient短暂的;;临时的)
Properties
-
Properties是一个Map体系的集合类
-
Properties可以保存到流中或从流中加载;属性列表中的每一个键及其对应的值都是一个字符串。
-
创建集合对象:
Properties prop = new Properties();
Properties作为集合的特有方法
- Object setProperty(String key, String value)
设置集合的键和值,都是String类型,底层调用Hashtable方法的put。 - String getProperty(String key)
使用此属性列表中指定的键搜索属性。 - Set
stringPropertyNames( )
从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串。
Properties和IO流结合的方法
读取数据
- void load(InputStream inStream)
从输入字节流读取属性列表(键和元素对)。 - void load(Reader reader)
以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。
写入数据
- void store(OutputStream out, String comments)
将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法加载到 Properties表中的格式输出流。 - void store(Writer writer, String comments)
将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式输出到输出字符流。
线程和进程
进程
- 正在运行的程序;
- 是系统进行资源分配和调运的独立单位;
- 每一个进程都有它自己的内存空间和系统资源。
线程(Thread)
- 是进程中的单个顺序控制流,是一条执行路径。
单线程
- 一个进程只有一条执行路径
多线程
- 一个进程有多条执行路径
多线程的实现方法
方法1:继承Thread类
- 定义一个类MyThread继承Thread类
- 在MyThread类中重写run()方法
- 创建MyThread类的对象
- 启动线程(用start()方法)
两个问题
- 为什么重写run()方法?
因为run()是用来封装被线程执行的代码。 - run方法和start()方法的区别?
- run():封装线程执行的代码,直接调用,相当于普通方法的调用。
- start():启动线程,然后由JVM调用此线程的run()方法。
方法2:实现Runnable接口
- 定义一个类myRunnable实现Runnable接口。
- 在myRunnable类中重写run方法。
- 创建myRunnable对象。
- 创建Thread对象,将 3 中的创建的对象作为构造方法的参数
Thread windows1 = new Thread(sellTicket, "一号窗口");
Thread的构造方法可以设置线程的名称。 - 启动线程( start() )
Thread设置和获取线程名称
-
设置
//将该线程的名称更改为等于参数name void setName(String name)
//通过MyThread类构造有参构造方法 public MyThread(String name){ super(name); }
-
获取
- String getName():返回此线程的名称
- static Thread currentThread( ):
返回对当前正在执行的线程对象的引用 - Thread.currentThread().getName()
获取当前正在执行的线程名
线程调度
分时调度模型
- 是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片。
抢占式调度模型(java使用该模型)
- 是指优先让优先级高的线程占用CPU,如果线程的优先级相同,那么就随机选择一个线程,使其占用CPU。优先级高的线程获取的CPU时间片相对多一些多线程程序的执行是有随机性。
Thread类中设置和获取线程优先级的方法
- public final int getPriority( ):
返回此线程的优先级 - public final void setPriority(int newPriority):
更改此线程的优先级- 线程的默认优先级是:5
- 线程优先级的范围是:1-10
- 优先级高仅仅代表获取的CPU时间片的几率高,
不代表它一定跑在最前面。
线程控制
- void join()
等待这个线程死亡(执行完毕以后)。
mt1.start();mt1.join(); - static void sleep(long millis)
使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 - void setDaemon(boolean on)
将此线程标记为 守护(daemon)线程或用户线程。 当运行的线程是守护线程时,Java虚拟机将退出。
线程同步
判断是否存在多线程安全问题
- 同时满足以下三个条件,就会出现多线程安全问题
- 是否是多线程环境
- 是否有数据共享
- 是否有多条语句操作共享数据
解决多线程安全问题
- 解决思路
- 让程序没有安全问题的环境。
- 破坏上述三条环境之一就行,其中主要是破坏条件3。
- 就是把多条语句操作共享数据的代码锁起来,让任意时刻只能由一个线程执行即可。
实现方法
同步代码块
- 格式:
synchronized(任意对象){
//多条语句操作共享数据的代码
}
- 范例:
//创建一个任意类型的锁对象
private Object obj = new Object();
//将锁obj添加到synchronized中
synchronized(obj){
// 多条语句操作共享数据的代码
}
- 好处与弊端
- 好处:解决了多线程的数据安全问题。
- 弊端:当线程很多时,每个线程都需要判断同步上的锁,耗费资源。
同步方法
-
同步非静态方法
- 就是把synchronized关键字加到方法上
- 格式:
修饰符synchronized返回值类型 方法名(方法参数){ } - 同步方法的锁对象是什么?(this它自身)
-
同步静态方法
- 格式:
修饰符static synchronized返回值类型 方法名(方法参数){ } - 同步静态方法的锁对象是什么?(类名.class)
- 格式:
Lock接口
-
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。
-
Lock是接口不能直接实例化,采用它的实现类ReentrantLock来实例化。
? -
内部方法
- void lock()获得锁
- void unlock()释放锁
-
实现类(ReentrantLock)
- 构造方法:
ReentrantLock( )创建一个ReentrantLock实例
- 构造方法:
-
范例:
private Lock lock = new ReentrantLock();
try {
lock.lock();
//执行的代码程序
}finally {
lock.unlock();
}
线程安全的类
StringBuffer(字符串缓冲区)
- 线程安全,可变的字符序列(StringBuilder)
- 它就是执行同步的StringBuilder(字符串拼接)
Vector(向量)
-
执行同步的ArrayList
-
多线程同步程序中,现在基本不使用该类;
-
替换成List
list = Collections.synchronizedList(new ArrayList ()); -
该方法创建同步的ArrayList数组
Hashtable(哈希表)
-
执行同步的HashMap
-
多线程同步程序中,现在基本不使用该类;
-
替换成Map
map = Collections.synchronizedMap(new HashMap ()); -
该方法创建同步的Map集合
网络编程
网络编程入门
IP地址
- IP:它是网络中设备的唯一标识。
- InetAddress类
- static InetAddress getByName(String host)
确定主机名称的IP地址。 - static InetAddress getLocalHost()
返回本地主机的地址。 - String getHostAddress()
返回文本显示中的IP地址字符串。 - String getHostName()
获取此IP地址的主机名。
端口
- 端口号:设备上应用程序的唯一标识。
- 它是用两个字节表示的整数,取值范围是0~65535。其中,0-1023用于知名的网络服务和应用,普通的应用程序应使用1024以上的端口号。
- 如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
协议
- UDP协议(用户数据报协议)
- TCP协议(传输控制协议)
UDP协议
- UDP通信原理:它是一种不可靠的网络协议,在通信的两端个建立一个Socket对象,但是这两个Socket只负责发送、接受数据的对象,不确保数据是否丢失socket(插口)。
UDP发送数据
//1.创建发送端的Socket对象
//构造数据报套接字并将其绑定到本地主机上的任何可用端口。
DatagramSocket ds = new DatagramSocket();
//2.创建数据,并把数据打包
//构造用于发送长度为length的分组数据报包,指定主机上到指定的端口号。
DatagramPacket(byte[] buf, int length, InetAddress address, int port) ;
//3.调用DatahramSocket对象的方法发送数据
void send(DatagramPacket p);
//4.关闭发送端
void close();
UDP接受数据
//1.创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(int port);
//2.建立一个数据包,用来接受数据
DatagramPacket(byte[] buf, int length);
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//3.调用DatagramSocket对象的方法接收数据
void receive(DatagramPacket p);
//4.解析数据包,并把数据在控制台显示
byte[] getData();
int getLength();
System.out.println(new String(bys, 0, dp.getLength()));
//5.关闭接受端
void close();
TCP协议
- 客户端提供了Socket类,服务器端提供了ServerSocket类。
TCP发送数据(客户端)
//1.创建客户端Socket对象
Socket(String host,int port );
//2.获取输出流,写入数据
OutputStream getOutputStream();
//3.释放资源
void close();
TCP接收数据(服务器端)
//1.创建服务器端的Socket对象
ServerSocket(int port);
//2.监听客户端连接,返回一个Socket对象
Socket accept();
//3.获取输入流,读取数据,并把数据显示在控制台
InputStream getInputStream( );
//4.释放资源
void close();
数据传输流程
-
客户端:数据来自文本文件,接收服务器反馈
-
服务器:接收到的数据写入文本文件,给出反馈
-
出现问题:程序一直等待。
-
原因:读取数据的方法是阻塞式的。
-
解决方法:使用Socket类的shutdownOutput()方法
-
Lambda表达式
- Lambda表达式的格式 :(形参) -> {代码块}
- 作用范围:只能在调用接口时使用。
Lanbda表达式的注意事项
- 有一个接口,接口中有且仅有一个抽象方法。
- 必须要有上下文环境,才能推导出Lambda对应的接口。
- 根据局部变量的赋值得知Lambda对应的接口
Runnable r = () -> System.out.println("Lambda表达式"); - 根据调用方法的参数得知Lambda对应的接口
new Thread(() -> System.out.println("Lambda表达式")).start();
- 根据局部变量的赋值得知Lambda对应的接口
Lambda表达式的省略模式
- 参数类型可以省略
//它俩的效果是一样的
useAddable((x, y) -> {
retrun x+y;
});
useAddable((int x, int y) -> {
retrun x+y;
});
参数只有一个时,小括号可以省略
useEatable(s -> {
System.out.println(s);
});
代码块的语句只有一条时,大括号和分号可以省略
useEatable(s -> System.out.println(s));
//如果有return,也可以省略return
useAddable((x, y) -> x+y);
//和下面的代码效果一样
useAddable((x, y) -> {retrun x+y;});
Lambda表达式和匿名内部类的区别
作用类型不同
- 匿名内部类:可以是接口、抽象类、具体类。
- Lambda表达式:只能是接口。
使用限制不同
- 接口中有且只有一个抽象方法,Lambda表达式,匿名内部类都行。
- 接口中有多个抽象方法,只能使用匿名内部类。
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件。
- Lambda表达式:编译之后,不会生成一个单独的.class字节码文件;对应的字节码会在运行中动态生成。
方法引用
-
方法引用符:
::
该符号为引用运算符,它所在的表达式被称为方法引用。 -
举例:
usePrintable(System.out::println);
//与下面的代码效果相同
//Lambda表达式:
usePrintable(s -> System.out.println(s));
- 推导与省略
- 使用
Lambda
和方法引用
,可根据可推导就是可省略的原则,无需指定参数类型、重载形式,它们都可以被自动推导。 - 方法引用就是Lambda的孪生兄弟。
- 使用
Lambda表达式支持的方法引用
引用类方法
- 含义:就是引用类的静态方法。
- 格式:
类名::静态方法
- 范例:
//Integer类的方法:Public static int parseInt(String s )将此String转换为int类型数据
Integer::parseInt
引用对象的实例方法
- 含义:就是引用类中的成员方法。
- 格式:
对象名::成员方法
。对象名 - 范例:
PrintString ps = new PrintString();
useConverter(ps::toUpperCase());
//与下面的代码效果一致
useConverter(s -> s.toUpperCase());
引用类的实例方法
- 含义:就是引用类中的成员方法。
- 格式:
类名::成员方法
。类名 - 范例:
//该引用类方法,和引用对象的实例方法类似,将对象改为类名即可。
String::substring
//Lambda表达式被类的实例方法代替时,第一个参数作为调用者,后面的参数全部传递给该方法作为参数。
useMyString((s,x,y) -> s.subString(x,y));
useMyString(String::subString);
引用构造器
- 含义:就是引用构造方法
- 格式:
类名::new
- 范例:
Student::new
useStudentBuilder(Student::new);
//与下面的代码效果一致
useStudentBuilder((name, age) -> new Student(name, age));
函数式接口
-
有且仅有一个抽象方法的接口,java中的函数式编程体现就是Lambda表达式。
-
标记接口是函数式接口
- @FunctionalInterface 在该接口上标记该注解。
- 放在接口定义的上方:如果接口是函数式接口,编译通过;否则编译失败
-
函数式接口作为方法的参数
-
函数式接口作为方法的返回值
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为结果返回。
private static Comparator getComparator(){
return (s1, s2) -> s1.length()-s2.length();
}
常用的函数式接口
Supplier(生成数据)接口
- public interface Supplier
代表结果供应商。 - Supplier
:包含一个无参的方法(T get():获得结果)
该方法不需要参数,他会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。 - Supplier
接口也称为生产型接口
我们指定了接口的泛型是什么,get方法就会生产什么类型的数据供我们使用。
Consumer(操作数据)接口
- Stream.Builder
表示接受单个输入参数并且不返回结果的操作。 - void accept(T t)
对给定的参数执行此操作。 - default Consumer
andThen(Consumer<? super T> after)
返回一个组合的 Consumer ,按顺序执行该操作,然后执行 after操作。
Predicate(判断数据)接口
- public interface Predicate
表示一个参数的判断(布尔值函数)。 - boolean test(T t)
在给定的参数上评估这个判断。 - default Predicate
and(Predicate<? super T> other)
返回一个组合的谓词,表示该判断与另一个判断的短路逻辑AND。 - default Predicate
or(Predicate<? super T> other)
返回一个组合的判断,表示该判断与另一个判断的短路逻辑或。 - default Predicate
negate()
返回表示此判断的逻辑否定的判断。
Function接口
public interface Function
表示接受一个参数并产生结果的函数。
- R apply(T t)
将此函数应用于给定的参数。 - default
Function andThen(Function<? super R,? extends V> after)
返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果。 - default
Function compose(Function<? super V,? extends T> before)
返回一个组合函数,首先将 before函数应用于其输入,然后将此函数应用于结果。
Stream流
- Stream流把真正的函数式编程风格引入到Java中。
范例:
//生成流-->过滤出姓张的-->过滤出长度为3的-->逐一打印
arrays.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3).forEach(System.out::println);
Stream流的使用
生成流
- 通过数据源(集合,数组等)生成流list.stream()。
中间操作
- 一个流后面可以跟零或多个中间操作,其目的主要是打开流,做出某些程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用。filer()
总结操作
- 一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。forEach( )
Stream流的生成方式
-
将集合中的数据转换成流
-
Collection体系的集合直接的生成流
//Collection体系的集合可以使用默认方法stream()生成流,default Stream stream()
List list = new ArrayList();
Stream listStream = list.stream();
Set set = new HashSet();
Stream setStream = set.stream();
- Map体系的集合间接的生成流
Map map = new HashMap();
Stream keyStream = map.keySet().stream();
Stream valueStream = map.values().stream();
Stream> entryStream = map.entrySet().stream();
- 数组体系调用静态方法生成流
//数组可以通过Stream接口的静态方法of(T...values)生成流
String[] strArray = {"hello", "world", "java"};
Stream strArrayStream = Stream.of(strArray);
Stream strArrayStream2 = Stream.of("hello", "world", "java");
Stream integerStream = Stream.of(1, 2, 3, 4, 5);
Stream流的收集操作
- 将流中的数据转换成集合
- Stream流的收集方式
R collect(Collector collector)
但是这个收集方式的参数是一个Collector接口。 - 工具类Collectors提供了具体的收集方式。
//把元素收集到List集合中
public static Collector toList()
//把元素收集到Set集合中
public static Collector toSet()
//把元素收集到Map集合中
public static Collector toMap(Function keyMapper, Function valueMapper)
//范例:
Set collect = age25up.collect(Collectors.toSet());
常见的中间操作方法
- Stream
filter(Predicate<? super T> predicate)
用于对流中的数据进行过滤 - Stream
limit(long maxSize)
返回由此流的元素组成的流,截取指定参数个数的数据 。 - Stream
skip(long n)
跳过指定参数个数的数据,返回由该流的剩余元素组成的流 - static
Stream concat(Stream<? extends T> a, Stream<? extends T> b)
合并a和b两个流为一个流 - Stream
distinct()
返回由该流的不同元素(根据 Object.equals(Object) )组成的流。 - Stream
sorted()
返回由此流的元素组成的流,根据自然顺序排序。 - Stream
sorted(Comparator<? super T> comparator)
返回由该流的元素组成的流,根据提供的 Comparator进行排序。 Stream map(Function<? super T,? extends R> mapper)
返回由给定函数应用于此流的元素的结果组成的流。- IntStream mapToInt(ToIntFunction<? super T> mapper)
- 返回一个 IntStream ,其中包含将给定函数应用于此流的元素的结果。
- intStream:表示原始int流
int sum() 返回此流中元素的总和。 - 范例:int sum = arrays.stream().mapToInt(Integer::parseInt).sum();
- ToIntFunction接口中的方法
int applyAsInt(T value)
常见的终结操作方法
- void forEach(Consumer<? super T> action)
对此流的每个元素执行操作。 - long count()
返回此流中的元素数。
反射
类加载器
类加载器的作用
- 负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象
类加载
- 当程序要使用某个类时,如果该类还未被加载到内存中,侧系统会通过【类的加载、类的连接、类的初始化】来对类进行初始化。类加载/类初始化
类的加载
- 就是指将class文件读入内存,并为之创建一个java.lang.Class对象
- 任何类被使用时,系统都会为之创建一个java.lang.Class对象
类的连接
验证阶段
- 用于检验被加载的类是否有正确的内部结构,并和其它类协调一致
准备阶段
- 负责为类的类变量(static变量)分配内存,并设置默认初始化值
解析阶段
- 将类的二进制数据中的符号引用替换为直接引用
类的初始化
类的初始化步骤
- 假如类还未被加载和连接,则程序先加载并连接该类
- 假如该类的直接父类还未被初始化,则向初始化其直接父类
- 假如类中有初始化语句,则系统依次执行这些初始化语句
类的初始化时机
- 创建类的实例,也就是new Object
- 调用类的类方法(static方法)
- 访问某个类或接口的静态变量,或者对静态变量赋值
- 使用反射方式来强制创建摸个类或接口对应的java.lang.Class对象
- 初始化一个类的子类
- 直接使用java.exe命令来运行某个主类
实现反射
获取Class类的对象
- 如果想通过反射使用一个类,首先获取该类的字节码文件对象,也就是类型为Class类型的对象
三种方式获取Class类型的对象
-
使用类的class属性来获取该类对应的Class对象
- Student.class将会返回Student类对应的Class对象
- Class
c1 = Student.class;
-
调用对象的getClass()方法,返回该对象所属类对应的Class对象
- 该方法是Object类中的方法,所有的Java对象都可以调用该方法
- Class<? extends Student> c2 = new Student().getClass();
-
使用Class类中的静态方法forName(String className)
- 该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径
- Class<?> c3 = Class.forName("day12.Student");
获取构造方法并使用
获取该类所有的构造方法
-
Constructor<?>[] getConstructors()
-
返回包含一个数组 Constructor对象反射由此表示的类的所有【公共构造】(public)类对象
-
Constructor<?>[] getDeclaredConstructors()
-
返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。
获取该类指定的构造方法
-
Constructor
getConstructor(Class<?>... parameterTypes) -
返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
- Constructor类中用于创建对象的方法
- T newInstance(Object...initargs):根据指定的构造方法创建对象
-
Constructor
getDeclaredConstructor(Class<?>... parameterTypes) -
返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
- 把对应参数的数据类型字节码,做为getConstructor方法的形参传给它
- Constructor<? extends Student> con = studentClass.getConstructor(String.class,int.class,String.class);
- 不用封装的数据类型类,直接使用基本数据类型(int、long等)调用class属性
暴力反射
- public void setAccessible(boolean flag)
- 值为true,取消访问检查。使其私有构造方法也可以使用
获取成员变量并使用
获取该类所有的成员变量
-
Field[] getFields();
-
返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。
-
Field[] getDeclaredFields();
-
返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。
获取该类指定的成员变量
-
Field getField(String name);
-
返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。
-
Field getDeclaredField(String name);
-
返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。
给成员变量赋值的方法
- void set(Object obj, Object value);
- 给obj对象的成员变量赋值为value
获取成员方法并使用
获取该类所有的成员方法
-
Method[] getMethods();
-
返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
-
Method[] getDeclaredMethods();
-
返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。
获取该类指定的成员方法
-
Method getMethod(String name, Class<?>... parameterTypes);
-
返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
-
Method getDeclaredMethod(String name, Class<?>... parameterTypes);
-
返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。
调用对象的成员方法
- Object invoke(Object obj, Object... args);
- 在具有指定参数的 方法对象上调用此 方法对象表示的底层方法。
运行配置文件指定内容
//创建集合
Properties prop = new Properties();
//配置文件流
FileReader fr = new FileReader("idea_test\\srcFile.txt");
//加载数据
prop.load(fr);
fr.close();
//获取类名和方法名
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
//创建class对象
Class<?> c = Class.forName(className);
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method m = c.getMethod(methodName);
m.invoke(obj);