抛异常:
e.getMessage()
e.toString()
e.printStackTrace()
Colletion常用方法:add remove contains clear isEmpty size
--------------------List--------------------------------------------
List特点:
1.有序:存储和取出的元素顺序一致
2.可重复:存储的元素可以重复
List特有方法:
add:插入指定位置
remove:删除指定索引处的元素,返回被删除的元素
set: 修改指定索引处的元素,返回被修改的元素
get: 返回指定索引处的元素
Iterator迭代器遍历集合的时候不能对原有集合做出增加或者删除操作,会导致next()报错
应该用for循环遍历或者List特有的迭代器ListIterator遍历
ListIterator 双向链表 可以反方向遍历
LinkedList特有方法:
addFrist:头插
addLast: 尾插
getFrist: 返回第一个元素
getLast: 返回最后一个元素
removeFrist: 删除并返回第一个元素
removeFrist: 删除并返回最后一个元素
———————————Set--------------------------------------------------
Set没有特有方法,都是collection的方法
对迭代顺序不作保证 添加顺序与输出顺序不同
但是Set集合中不允许存在重复元素
而且没有索引的方法,所以不能使用普通for循环遍历
只能用加强for循环和迭代器 加强for循环本质上是迭代器
HashSet
底层数据结构是哈希表
要保证元素唯一性,就要重写hashCode()和equals()方法
哈希表默认初始长度是16
LinkedHashSet
由链表和哈希表实现
链表保证元素有序,哈希表保证元素唯一
TreeSet
元素有序:按照一定的规则排序,排序方式取决于构造方法
无参构造:自然排序
带参构造:根据指定的比较器进行排序
没有索引
Comparable自然排序
创建的类继承comparable接口 重写compareTo方法
--------------------------类型通配符--------------------------
类型通配符 <?>
List<?> list1=new ArrayList<Object>();
List<?> list2=new ArrayList<Number>();
List<?> list3=new ArrayList<Integer>();
上限通配符 <? extends 类型> 只能new他本身或者他的子类
List<? extends Number> list4 =new ArrayList<Number>();
List<? extends Number> list5 =new ArrayList<Integer>();
下限通配符 <? super 类型> 只能new他本身或者他的父类
List<? super Number> list6 =new ArrayList<Number>();
List<? super Number> list7 =new ArrayList<Object>();
----------------------------可变参数-------------------------
public class Demo {
public static void main(String[] args) {
System.out.println(sum(10,20));
System.out.println(sum(10,20,30,40));
}
public static int sum(int... a)
{
int sum=0;
for(int i: a)
{
sum+=i;
}
return sum;
}
}
int... a 其实是个数组
如果一个方法有多个参数,包含可变参数可变参数要放在最后
例如:sum(int b,int c ,int...a)
注意:静态方法只能调用静态方法
----------------------------------Map—————————————————————
Map集合的基本功能:
put
remove: 根据key删除相应的key-value,并返回相应的value
clear
contiansKey boolean
containsValue boolean
isEmpty boolean
size int
Map集合的获取功能:
get(Object key)
Set<K> keySet 获取是所有键的集合
Collection<V> values() 获取所有值的集合
Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象的集合
遍历Map的两种方法:
Map<String,String> map = new HashMap<String ,String>();
map.put("yangguo","xiaolongnv");
map.put("guojing","huangrong");
---------------第一种--------------------
Set<String> keySet = map.keySet();
for(String key:keySet)
{
String values = map.get(key);
System.out.println(key+","+values);
}
---------------第二种---------------------
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for(Map.Entry<String, String> i:entrySet)
{
String value = i.getValue();
String key = i.getKey();
System.out.println(key+","+value);
}
注意:当Map的键是对象而不是String的时候 为确保唯一性需要在对象类中重写hashCode和equals方法
--------------------------------Collections--------------------------------
不用new实体对象 直接调用
Collections.sort(list);对list集合进行排序
reverse(list) 反转
shuffle(list) 随机排序
----------------------------------File-------------------------------
boolean createNewFile() 当具有该名称的文件不存在时,创建一个由该抽象路径名
命名的新空文件
boolean mkdir() 创建由此抽象路径名命名的目录
boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
File类判断和获取功能
isDirectory: 判断是否为目录
isFile: 判断是否为文件
exists: 判断是否存在
getAbsolutePath: 返回此抽象路径名的绝对路径名字符串
getPath: 将此抽象路径名转化为路径字符串
getName: 返回名称
list: 返回目录中的文件和目录的名称字符串数组
listFiles: 返回目录中的文件和目录的File对象数组
File类删除功能
delete()
递归获取ff目录下所有文件和目录
public static void diGui(File ff)
{
File[] files = ff.listFiles();
if(files!=null) {
for (File i : files) {
if (i.isDirectory())
{
diGui(i);
}
else
System.out.println(i.getAbsolutePath());
}
}
}
-----------------------------------I/O------------------------------
I/O流分类:
按照数据的流向:
输入流:读数据
输出流:写数据 文件输出流用于将数据写入File ascll形式表示
按照数据类型来分:
字节流:字节输入流 字节输出流
字符流: 字符输入流 字符输出流
具体使用什么流:
记事本打开不是乱码 可以读懂 用字符流 否则用字节流
不知道用什么流的时候用字节流
所有和I/O相关的操作都要.close();
----------------------------------字节流------------------------------
字节流写数据的3种方式:
write(int b) 将指定的字节写入此文件输出流一次写一个字节数据,一次写一个字节数据
writer(byte[] b)将b.length字节从指定的字节数组写入此文件输入流 一次写一个字节数组数据
write(byte[] b,int off,int len)将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
一次写一个字节数组的部分数据
FileOutputStream f =new FileOutputStream(new File("test\\java.txt"));
//第一种
f.write(1);
//第二种
byte[] bytes = "abcde".getBytes();
f.write(bytes,1,2);
//数字是起始位置
//第三种
f.write(bytes);
f.close();
换行windos:\r\n或者\n linux:\n mac:\r
追加字符:构造输出流的时候在构造参数中第二的参数为true,
并将字节写入文件的末尾
finally:在异常处理是提供finally块来执行所有清楚操作
特点:在finally控制的语句一定会执行,除非JVM退出
字节流读数据的3种方式:
//第一种
read(); 一次读一个字节 需要进行(char)类型转换 文件末尾输出-1;
while((by = file.read())!= -1)
{
System.out.print((char)by);
}
//第二种
read(byte[] b);从该输入流读取最多b.length个字节的数据到一个字节数组
FileInputStream f =new FileInputStream(new File("test\\java.txt"));
byte[] bytes = new byte[10];
f.read(bytes);
System.out.println(new String(bytes));
f.close();
/r之类的字节也占用一个字节 其中f.read(bytes)返回的是读取的字节的个数
每读取一次 回替换byte数组里的元素
//最标准操作
FileInputStream f =new FileInputStream(new File("test\\java.txt"));
byte[] bytes = new byte[1024];
int len;
while((len=f.read(bytes))!=-1)
{
System.out.println(new String(bytes,0,len));
}
f.close();
//字节缓冲流
BufferedInputStream h=new BufferedInputStream(new FileInputStream(""));
BufferedOutputStream g=new BufferedOutputStream(new FileOutputStream(""));
//复制视频
基本字节流一次读写一个字节 耗时:64565毫秒
基本字节流一次读写一个字节数组 耗时:107毫秒
字节缓冲流一次读写一个字节 耗时: 405毫秒
字节缓冲流一次读写一个字节数组 耗时: 60毫秒
------------------------------------字符流-------------------------
为什么出现字符流?
一个汉字存储:
如果是GBK编码,占用2个字节
如果是UTF-8编码,占用3个字节
这时候字节流文本文件数据会出现乱码
汉字无论使用哪种方法存储,第一个字节都是负数
字符流=字节流+编码表
字符流初始化:
OutputStreamWriter l = new OutputStreamWriter(new FileOutputStream(""));
InputStreamReader q = new InputStreamReader(new FileInputStream(""));
编码解码:
OutputStreamWriter l = new OutputStreamWriter(new FileOutputStream(""),"GBK");
InputStreamReader q = new InputStreamReader(new FileInputStream(""),"UTF-8");
字符流写数据的5种方式:
write(int c)
write(char[] buf)
wirte(char[] cbuf,int off,int len)
write(String str)
write(String str,int off,int len)
注意:字符流的write操作执行完之后,字符还在缓冲区内,需要调用flush()才能写入文件
close()先刷新后关闭
字符流读数据的2种方式:
read() 一次读一个字符数据
read(char[] cbuf) 一次读一个字符数组数据
//字符流初始化太麻烦了所以用他们的子类
但是想解决编码解码问题还得用其父类
FileReader a =new FileReader("");
FileWriter b =new FileWriter("");
//字符缓冲流
BufferedReader a = new BufferedReader(new FileReader(""));
BufferedWriter b = new BufferedWriter(new FileWriter(""));
字符缓冲流特有功能
BufferedWriter
void newLine(): 写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader
public String readLine(): 读一行文字。结果包含行的内容的字符串,不包括任何
行终止字符,如果流的结尾已经到达,则为null
-----------------------------------异常处理--------------------------
try(FileReader a = new FileReader("test\\java.txt");
FileWriter b = new FileWriter("test\\java1.txt");){
char[] chars = new char[1024];
int len;
while((len=a.read(chars))!=-1)
{
b.write(new String(chars,0,len));
}
}catch(IOException e)
{
e.printStackTrace();
}
//JDK7新加的异常处理方式 try catch finally太过复杂 这种处理方式自动close
-------------------------------特殊操作流----------------------------
标准输入流:
InputStream is = System.in;
字节流转化为字符流
InputStreamReader isr = new InputStreamReader(is);
一次读取一行数据的方法是字符缓冲输入流的特有方法
转换:
BufferedReader br = new BufferedReader(isr);
最终形式:BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
标准输出流:
PrintStream ps = System.out;
//System.out的本质是一个字节输出流
//打印流:
打印流特点:只负责输出数据,不负责读取数据
有自己的特有方法。
字节打印流: PrintStream(String fileName):使用指定的文件名创建新的打印流
字符打印流: PrintWriter(String fileName)
PrintWriter(Writer out,boolean autoFlush) //自动刷新不用调用flush();
特有方法:ps.println(97); 写入的文件内容就是97 而不是a
对象序列化流:ObjectOutputStream
对象反序列化流:ObjectInputStream
-----------------------------Peoperties和IO流结合--------------------
Peoperties作为集合Map的使用 不是泛型类 每个键值都是Object类型的
Peoperties prop = new Peoperties();
特殊方法:setProperty(String,String) 底层调用的是put(Object,Object)
stringPropertyNames() 返回字符串键集Set
getProperty(key) 得到值
void load(Reader reader)从输入字符流读取属性列表(键和元素对)
void store(Writer writer,String comments)将此属性列表写入此properties
表中,以适合使用load方法的格式写入字符流
----------------------------进程和线程----------------------
进程:是正在运行的程序
系统进行资源分配和调用的独立单位
每一个进程都有它自己的内存空间和系统资源
线程: 是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则成为单线程程序
多线程:一个进程如果有多条执行路径,则成为多线程程序
//多线程的实现方式:
-----------------------方式1:继承Thread类----------------------------
方式一:
定义一个类MyThread继承Thread类
在MyThread类中重写run()方法
创建MyThread类的对象 调用start方法
启动线程
为什么要重写run()方法?
因为run()是用来封装被线程执行的代码
run()方法和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后又JVM调用此线程的run()方法
//设置和获取线程名称 Thread类中的方法:
void setName(String name)
String getName()
在子类中创建带参构造方法
MyThread(String name){
super(name);
} 可以直接setName
static Thread currentThread() 返回对当前正在执行的线程对象的引用
Thread.currentThread().getName()
//线程调度
1.分时调度模型
2.抢占式调度模型:优先级 相同时随机选择一个
java使用的是2;
public final int getPriority():返回此线程的优先级
public final void setPriority(int newPriority): 更改此线程的优先级
优先级范围1-10 默认是5
线程优先级高仅仅表示线程获取的CPU时间片的几率高,但是要在此说比较多
或者多次运行的时候才能看到想要的效果
//线程控制
static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数
void jion() 等待这个线程死亡
void setDaemon(boolean on)将此线程标记为守护线程,当运行的线程都是守护线程
时,java虚拟机将退出
--------------------------方式2:实现Runnab接口----------------------
方式二:
定义一个类MyRunnable实现Runnable接口
在MyRunnable类中重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程
----------------------------线程同步--------------------------------
判断多线程程序是否会有数据安全问题的标准
是否是多线程环境
是否有共享数据
是否有多条语句操作共享数据
如何解决多线程安全问题?
基本思想:让程序没有安全问题的环境
怎么实现呢?
把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可
java提供了同步代码块的方式来解决:
synchronized(Object object){
多条语句操作共享数据的代码
} 相当于给代码加锁了,object就可以看成是一把锁
//同步方法:把synchronized加到方法上
private synchronized void sell();
同步方法的锁对象是 this
//同步静态方法: 就是把synchronized关键字加到静态方法上
private static synchronized void sell();
同步静态方法的锁对象是 类名.class
-----------------------------线程安全的类----------------------------
StringBuffer
线程安全,可变的字符序列
通常使用StringBuilder类,因为它支持所有相同的操作,但它更快,因为它不执行同步
Vector
Vector改进了List接口,Vector是线程安全的,没有要求时使用ArrayList
Hashtable
Hashtable被同步,线程安全。没有要求时,使用Hashmap
返回由指定列表支持的同步列表
List<String> list = Collections.synchronizedList(new ArrayList<String>());
//Lock锁:private Lock lock = new ReenttrantLock();
lock.lock(); lock.unlock();
//void wait() 导致当前线程等待,直到另一个线程调用该对象的notify()方法或者notifyAll()方法
void notify() 唤醒正在等待对象监视器的单个线程
void notifyAll() 唤醒正在等待对象监视器的所有线程
------------------------------网络编程------------------------------
网络编程:在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换
网络编程三要素:IP地址 每台计算机指定一个标识号
端口 端口号可以唯一标识设备中的应用程序
协议 位于同一个网络中的计算机在进行连接和通信的规则
//IP地址:
IPv4:32bit 点分十进制表示法
IPv6:采用128位地址长度,没16个字节一组,分成8组十六进制数
常用命令:ipconfig:查看本机IP地址
ping IP地址:检查网络是否连通
特殊IP地址:127.0.0.1是回送地址,可以代表本机地址,一般用来测试使用
InetAddress:此类表示Internet协议(IP)地址
static InetAddress getByName(String host)确定主机名称的IP地址
String getHostName() 获取此IP地址的主机名
String getHostAddress() 返回文本显示中的IP地址字符串
//端口:
取值范围:0-65535 其中0-1023用于一些知名网络服务和应用,普通的应用程序
使用1024以上的端口号,端口号被占用,会导致当前程序启动失败
//协议:
UDP协议 用户数据报协议 是无连接通信协议 数据的发送端和接收端不建立逻辑链接
消耗资源小,效率高,通常用于音频、视频和普通数据的传输
TCP协议 传输控制协议 是面向连接的通信协议 可以保证两台计算机之间的可靠无差错
的数据传输,TCP连接中必需要明确客户端与服务端,由客户端向服务端发出连接请求
每次连接的创建都需要经过三次握手 应用广泛:上传、下载文件、浏览网页
----------------------------高频面试三次握手-----------------------
三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务端之间的三次交互,以保证连接的可靠
第一次握手:客户端向服务器端发出连接请求,等待服务器确认
第二次握手:服务端向客户端回送一个响应,通知客户端收到了连接请求
第三次握手:客户端再次向服务器端发送确认信息,确认连接
UDP发送数据:
1.创建数据发送端的Socket对象(DatagramSocket)
2.创建数据,并把数据打包
3.调用DatagramSocket对象的方法发送数据
4.关闭发送端
DatagramSocket socket = new DatagramSocket();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line= reader.readLine())!=null){
if("886".equals(line)) break;
byte[] bytes = line.getBytes();
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getByName("192.168.0.8"),10086);
socket.send(packet);
}
socket.close();
UDP接收数据:
1.创建接收端的Socket对象(DatagramSocket)
2.创建一个数据包,用于接收数据
3.调用DatagramSocket对象的方法接收数据
4.解析数据包,并把数据在控制台显示
5.关闭接收端
DatagramSocket socket = new DatagramSocket(10086);
while(true){
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
socket.receive(packet);
System.out.println("数据是:"+new String(packet.getData(),0,packet.getLength()));
}
TCP发送数据的步骤
1.创建客户端的Socket对象(Socket)
2.获取输出流,写数据
3.释放资源
//Socket socket = new Socket(InetAddress.getByName("192.168.0.8"), 10086);
Socket socket = new Socket("192.168.0.8", 10086);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello world".getBytes());
socket.close();
TCP接收数据:
1.创建服务器端的Socket对象(ServerSocket)
2.获取输入流,读数据,并把数据显示在控制台
3.释放资源
ServerSocket ss = new ServerSocket(10086);
Socket socket = ss.accept();
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
String s = new String(bytes, 0, len);
System.out.println("数据是"+s);
socket.close();
ss.close();
客户端和服务器端的数据传输时靠socket对象的字节流传输的 get方法可以得到字节
流对象 可人为转化成字符流
客户端 服务器端都使用文件的时候 客户端应当调用socket.shutdownOutput()方法
标志着文件传输完毕 否则服务器端不知道文件是否传输完毕 一直处于等待
读数据的状态
--------------------------------函数式编程---------------------------
组成Lambda表达式的三要素:形式参数,箭头,代码块
使用前提: 有一个接口 接口中有且仅有一个抽象方法
//(实施参数)->{代码块} 如果代码块只有一行代码 可以省略大括号和分号
仅在这种情况下,如果return也可以省略
匿名内部类:编译之后,产生一个单独的.class字节码文件
Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在
运行的时候动态生成
接口的组成: 常量 public static final
抽象方法 public abstract
默认方法(java 8) public default void show3(){} public可省略
默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default
静态方法(java 8)接口中的静态方法只能接口调用 Inter.test();
私有方法(java 9)
方法引用符 ::
该符号为引用运算符,而它所在的表达式被称为方法引用
函数式接口
用@FunctionalInterface注解
常用的函数式接口
Supplier接口
get() 获得结果 返回数据
Consumer接口
void accpt(T t) 接收数据进行操作 不返回结果
default Consumer<T> andThen(Consumer after) 返回一个组合的Consumer,
依次执行此操作,然后执行after操作
Predicate接口
boolean test(T t) 判断,返回一个布尔值
default Predicate<T>negate() 返回一个逻辑的否定,对应逻辑非
default Predicate<T>and(Predicate other) 返回一个组合判断,对应短路与
default Predicate<T>or(Predicate other) 返回一个组合判断,对应短路或
Function<T,R>接口
R apply(T t) 将此函数应用于给定的参数
default<V>Function andThen(Function after) 返回一个组合函数,首先将该函数
应用于输入,然后将after函数应用于结果
Function<T,R>接口通常用于对参数处理,转换 ,然后返回一个新的值
--------------------------------类加载器-----------------------------
//类加载
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接
,类的初始化这三个步骤来对类进行初始化。不出意外,JVM会连续完成这三个步骤,所以
有时候把这三个步骤统称为类加载或者类初始化
类的加载
就是指将class文件读入内存,并创建一个java.lang.Class对象
任何类被使用时,系统都会为之创建一个java.lang.Class对象
类的连接
验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
准备阶段:负责为类的类变量分配内存,并设置默认初始化值
解析阶段:将类的二进制数据中的符号引用替换为直接引用
类的初始化(主要是对类变量进行初始化)
加入类还未被加载和连接,则程序先加载并连接该类
加入该类的直接父类还未被初始化,则先初始化其直接父类
加入类中有初始化语句,则系统依次执行这些初始化语句
类的初始化时机
创建类的实例
调用类的方法
访问类或者接口的类变量,或者为该类变量赋值
使用反射方式来强制创建某个类或者接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
//类加载器
负责将.class文件加载到内存中,并为之生成对应的java.lang.Class对象
了解这个机制能更好的理解程序的运行
JVM的类加载机制
全盘负责:就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他
Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class
,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器
先从缓存区中搜素该Class,只有放缓存区中不存在该Class对象时,系统才会读取该类对应的
二进制数据,并将其转换成Class对象,存储到缓存区。
ClassLoader:是负责加载类的对象
方法: static ClassLoader getSystemClassLoader():返回用于委派的系统类加载器
ClassLoader getParent():返回父类加载器进行委派
Java运行时具有的内置加载器:
Bootstrap class loader
Platform class loader
System class loader
依次为父子关系
---------------------------------------反射-----------------------------
//java反射机制
是指在运行时获取一个类的变量和方法信息。然后通过获取到的信息来创建对象
,调用方法的一种机制,由于这种动态性,可以极大地增强程序的灵活性,程序不用在编译期就
完成确定,在运行期仍然可以扩展
-------------------------------
//获取Class类的对象
1.Student.class将会返回Student类对应的Class对象
2.getClass()方法。Object类中的方法
3.Class类中的静态方法forName(String className)字符串参数时某个类的全路径,也就是完整包名的路径
//Class类中用于获取构造方法的方法
Constructor<?>[]getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[]getDeclaredConstructors():返回所有构造方法对象的数组
Constructor<T>[]getConstructor(Class<?>...ParameterTypes):返回单个公共构方法对象
例如c.getConstructor(String.class,int.class,String.class)
Constructor<T>[]getDeclaredConstructor(Class<?>...ParameterTypes):返回单个构造方法对象
Constructor中用于创建对象的方法:
T newInstance(Object...initargs):根据指定个构造方法创建对象
//暴力反射
public void setAccessible(boolean flag):值为true,取消访问检查
con.setAccessible(true) 之后便可以使用类中的私有构造方法
--------------------------------
//获取成员变量
Field[] getFields() 返回公共成员变量
Field[] getDeclaredFields() 全部成全变量
Field getField(String name) 返回指定公共成员变量
Field getDeclaredField(String name) 返回单个成员变量对象
获取构造方法创建对象 返回指定成员变量a a.set(对象,赋值);
可以个类中对象的成员变量赋值
---------------------------------
//获取成员方法
Method[] getMethods()返回公共方法,包含继承的方法
Method[] getDeclaredMethods()返回本类所有方法
Method getMethods(String name,Class<?>...parameterTypes)返回一个方法对象
Method getDeclaredMethods(String name,Class<?>...parameterTypes)
调用方法:method.invoke(obj);
//案例
Properties pop = new Properties();
BufferedReader reader = new BufferedReader(new FileReader("test//java.txt"));
pop.load(reader);
reader.close();
String className = pop.getProperty("className");
String methodName = pop.getProperty("methodName");
//得到类
Class<?> aClass = Class.forName(className);
//得到构造方法
Constructor<?> constructor = aClass.getConstructor(int.class,String.class);
//创建对象
Object o = constructor.newInstance(14,"name");
//得到方法
Method method = aClass.getMethod(methodName);
//运行
method.invoke(o);
-------------------------------------注解----------------------------
JDK中预定义的一些注解
@Override:检测被该注解标注的方法是否时继承自父类(接口)的
@Deprecated:该注解标注的内容,表示已过时
@SuppressWarnings:压制警告 @SuppressWarnings("all")压制所有警告
//自定义注解
*格式:
元注解
public @interface 注解名称{}
*本质:注解本质上是一个接口,该接口默认继承Annotation接口
public interface MyAnno extends java.lang.annotation.Annotation{}
*属性:接口中的抽象方法
*要求:
1.属性的返回值类型(void不行,类也不行,其他都不行)
*基本数据类型
*String
*枚举
*注解
*以上类型的数组
2.定义了属性,在使用时需要给属性赋值
1.如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值
2.如果只有一个属性需要赋值,并且属性的名称是value,则value可省略,直接定义值即可。
3.数组赋值时,值使用{}包裹。若果数组中只有一个值,则{}可以省略
*元注解:用于描述注解的注解
*@Target:描述注解能够作用的位置
*ElementType取值:
*TYPE:可以作用于类上
*METHOD:可以作用于方法上
*FIELD:可以作用于成员变量上
*@Retention:描述注解被保留的阶段
*@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
*@Documented:描述注解是否被抽取到api文档中
*@Inherited:描述注解是否被子类继承
//在程序使用注解:获取注解中定义的属性值
1.获取注解定义的位置的对象 .Class .Method .Field
2.获取指定的注解 getAnnotation(Class)
3.调用注解中的抽象方法获取配置的属性值