网络编程、日志技术、枚举、类加载器、反射。
一、三要素
1.IP地址:设备在网络中的地址,是唯一的标识(包含ipv4和ipv6,ipv4计算方法是点号计算,ipv6是冒号计算)
2.端口:应用程序在设备中唯一的标识 一个端口只能被一个应用程序使用
3.协议:数据在网络中传输的规则,常见的规则有UDP和TCP协议
二、IP地址
常用命令
1、ipconfig:查看本机IP地址
2、pingIP地址:检查网络是否畅通
3.特殊IP:127.0.0.1是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
三、网络编程获取主机名和主机ip地址的方法
package com.study.socketDemo; import java.net.InetAddress; import java.net.UnknownHostException; public class InternetDemo { public static void main(String[] args) throws UnknownHostException { /* static InetAddress getByName(String host) 确定主机名称IP地址,主机名称可以是机器名称,也可以是ip地址 String getHostName() 获取此IP地址的主机名 String getHostAddress() 返回文本显示中的ip地址字符串 */ InetAddress address=InetAddress.getByName("LAPTOP-2G08AS7E"); String hostName= address.getHostName(); String ip= address.getHostAddress(); System.out.println("主机名为:"+hostName); System.out.println("IP地址为:"+ip); } }
四、两种协议
1.UDP协议
用户数据报协议
UDP是面向无连接通信协议
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
2.TCP协议
传输控制协议
TCP协议是面向连接的通信协议
速度慢,没有大小限制,数据安全
五、UDP案例
发送端
package com.study.socketdemo2; import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; public class ClientDemo { public static void main(String[] args) throws IOException { //1。找码头 DatagramSocket ds=new DatagramSocket(); //2.打包礼物 //DatagramPacket(byte[] buf,int length, InetAddress address,int port) String s="送礼物"; byte[] bytes=s.getBytes(); //本机的ip InetAddress address=InetAddress.getByName("127.0.0.1"); //想要发送 的端口 int port=10000; DatagramPacket dp=new DatagramPacket(bytes,bytes.length,address,port); //3.发送包裹 ds.send(dp); //4.付钱走人 ds.close(); } }
接收端
package com.study.socketdemo2; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class ServerDemo { public static void main(String[] args) throws IOException { //接收端 //1,赵码头 表示接收端从10000端口接收数据的 DatagramSocket ds=new DatagramSocket(10000); //2.创建一个箱子 byte[] bytes=new byte[1024]; DatagramPacket dp=new DatagramPacket(bytes, bytes.length); //3.接收礼物,把礼物放到新的箱子中 System.out.println("-----------接收前=------------"); ds.receive(dp); System.out.println("--------------接收后--------------"); //4.从新的箱子里面获取礼物 int length=dp.getLength(); System.out.println(new String(bytes,0,length)); //5.取完 ds.close(); } }
注意事项
1.要先运行接收端,在运行发送端(因为udp是无连接的,如果先运行发送端,没有接收端数据将会丢失)
2.如果接收端在启动之后,没有接收到数据,那么会死等
3.在接收数据的时候,需要调用一个getLength方法,表示接收了多少直接
六、UDP通讯程序
1.单播:一对一
2.组播:一对多
3.广播:一对所有
组播案例
package com.study.socketDemo4; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; public class ServiceDemo1 { public static void main(String[] args) throws IOException { MulticastSocket ms=new MulticastSocket(10000); DatagramPacket dp=new DatagramPacket(new byte[1024],1024); ms.joinGroup(InetAddress.getByName("224.0.1.0")); ms.receive(dp); byte[] data = dp.getData(); int length = dp.getLength(); System.out.println(new String(data,0,length)); ms.close(); } }
package com.study.socketDemo4; import com.study.socketDemo.InternetDemo; import java.io.IOException; import java.net.*; public class ClientDemo { public static void main(String[] args) throws IOException { DatagramSocket ds=new DatagramSocket(); String s="hello 组播"; byte[] bytes=s.getBytes(); InetAddress address=InetAddress.getByName("224.0.1.0");//组播地址 int port=10000; DatagramPacket dp=new DatagramPacket(bytes, bytes.length,address,port); ds.send(dp); ds.close(); } }
UDP广播
package com.study.socketDemo5; import java.io.IOException; import java.net.*; public class ClientDemo { public static void main(String[] args) throws IOException { DatagramSocket ds=new DatagramSocket(); String s="hello广播"; byte[] bytes=s.getBytes(); InetAddress address=InetAddress.getByName("255.255.255.255"); int port=10000; DatagramPacket dp=new DatagramPacket(bytes, bytes.length,address,port); ds.send(dp); ds.close(); } }
package com.study.socketDemo5; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class ServiceDemo { public static void main(String[] args) throws IOException { DatagramSocket ds=new DatagramSocket(10000); DatagramPacket dp=new DatagramPacket(new byte[1024],1024); ds.receive(dp); byte[] data = dp.getData(); int length = dp.getLength(); System.out.println(new String(data,0,length)); ds.close(); } }
七、TCP服务器与客户端
1.accept方法是阻塞的,作用就是等待客户端连接
2.客户端创建对象并连接服务器,此时通过三次握手协议保证跟服务器之前的连接
3,针对客户端来讲,是往外写的,所以是输出流针对服务器来讲,是往里读的,所以是输入流
4.read方法也是阻塞的
5.在关流的时候,还多了一个往服务器写结束标记的动作
6.最后一部断开连接,通过四次挥手协议保证连接终止
面试题
为什么四次挥手会比三次握手多一次?
因为服务器收到客户端的取消请求,会向服务器确认数据是否要取消,所以才会多一次。
Ip:是网络中设备的唯一标识
端口号:设备上应用程序的唯一标识
协议:计算机网络中,连接和通信的规则被称为网络通信协议
TCP:传输控制协议,是面向连接的通信协议,每次连接的创建都需要经过“三次握手”,可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等
UDP:用户数据报协议,无连接通信协议,使用UDP协议消耗系统资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
案例
package com.study.SocketDemo6; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class ClientDemo { public static void main(String[] args) throws IOException { //1.创建socket对象,参数为ip地址和端口 Socket socket=new Socket("127.0.0.1",10000); //2.使用IO流输入数据 OutputStream os=socket.getOutputStream(); os.write("hello,tcp".getBytes()); //3,释放资源 os.close(); socket.close(); } }
package com.study.SocketDemo6; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /* 1.accept方法是阻塞的,作用就是等待客户端连接 2.客户端创建对象并连接服务器,此时通过三次握手协议保证跟服务器之前的连接 3,针对客户端来讲,是往外写的,所以是输出流 针对服务器来讲,是往里读的,所以是输入流 4.read方法也是阻塞的 */ public class ServiceDemo { public static void main(String[] args) throws IOException { //1.创建服务器接收对象 ServerSocket ss=new ServerSocket(10000); //2.创建接收对象 Socket accept= ss.accept(); //3.创建输入流 InputStream is=accept.getInputStream(); //4.判断输入流是否为空,不为空就输出 int b; while ((b= is.read())!=-1){ System.out.println((char) b); } //释放资源 is.close(); ss.close();
socket.close(); } }
TCP程序文件上传练习
案例需求
-
-
-
客户端:数据来自于本地文件,接收服务器反馈
服务器:接收到的数据写入本地文件,给出反馈
-
案例分析
-
创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束
-
创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息
-
客户端接受服务端的回馈信息
-
-
-
-
package com.study.socketDemo8; import java.io.*; import java.net.Socket; public class ClientDemo { public static void main(String[] args) throws IOException { //创建socket对象 Socket socket=new Socket("127.0.0.1",9999); //2.创建本地的流,读取本地文件 BufferedInputStream bis=new BufferedInputStream(new FileInputStream("D:\\Desktop\\Develop\\Study3" + "\\socketmodule\\page\\aa.png")); //3.写到服务器--网络中的流 使用socket进行获取 OutputStream os=socket.getOutputStream(); //4.使用缓冲流进行输出,提升效率 BufferedOutputStream bos=new BufferedOutputStream(os); //5.进行判断输出 int b; while ((b= bis.read())!=-1){ bos.write(b);//如果本地文件不为空,就通过网路写到服务器中去 } bos.flush(); //给服务器一个标记,告诉服务器文件已经传输完毕 socket.shutdownOutput(); //接收服务器的反馈信息 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; while ((line= br.readLine())!=null){ System.out.println(line); } bis.close(); socket.close(); } }
package com.study.socketDemo8; import java.io.*; import java.net.ServerSocket; import java.net.Socket; /* 客户端:数据来自于本地文件,接收服务器反馈 服务器:接收到的数据写入本地文件,给出反馈 - 案例分析 - 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束 - 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息 - 客户端接受服务端的回馈信息 */ public class ServiceDemo { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(9999); Socket accept = ss.accept(); //使用网络中的流读取客户端传递过来的数据 对于服务器来说是输入 BufferedInputStream bis=new BufferedInputStream(accept.getInputStream()); //把本地的io流数据写到本地中,实现永久化存储 BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\Desktop\\Develop\\Study3\\socketmodule\\page\\copy.png")); //进行判断输出 int b; while ((b=bis.read())!=-1){ bos.write(b); } //给客户端进行反馈,提示是否上传成功 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); bw.write("上传成功"); bw.newLine(); bw.flush(); bos.close(); accept.close(); ss.close(); } }
总结:获取本地文件就是通过本地的io流在客户端使用bis获取,然后写到网络中的流去BOS,然后传递到服务端,在服务端先要获取网络中的流,写到服务器中也是 bis,然后获取的数据写到本地中实现存储使用bos,最后在来反馈
服务器优化
弊端:第二次上传文件的时候,会把第一次的文件给覆盖
改进方法:UUID.randomUUID() 方法生成随机的文件名
package com.study.socketDemo8; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.UUID; /* 客户端:数据来自于本地文件,接收服务器反馈 服务器:接收到的数据写入本地文件,给出反馈 - 案例分析 - 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束 - 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息 - 客户端接受服务端的回馈信息 */ public class ServiceDemo { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(10000); //加上while循环进行服务器优化,能使多个客户端获取 while (true) { Socket accept = ss.accept(); //获取网络流 BufferedInputStream bis=new BufferedInputStream(accept.getInputStream()); //本地的io流把数据写到本地中,实现永久化存储 BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\Desktop\\Develop\\Study3" + "\\socketmodule\\page\\ "+ UUID.randomUUID().toString()+".png")); int b; while ((b= bis.read())!=-1){ bos.write(b); } BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); bw.write("上传成功"); bw.newLine(); bw.flush(); bos.close(); accept.close(); } // ss.close(); } }
服务器优化二、
加入循环后引发了一个问题L使用循环虽然可以让服务器处理多个客户端请求,但是还是无法同时跟多个客户端通信
改进方法:开启多线程处理
package com.study.socketDemo9; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.UUID; /* 客户端:数据来自于本地文件,接收服务器反馈 服务器:接收到的数据写入本地文件,给出反馈 - 案例分析 - 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束 - 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息 - 客户端接受服务端的回馈信息 */ public class ServiceDemo { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(10000); //加上while循环进行服务器优化,能使多个客户端获取 while (true) { Socket accept = ss.accept(); ThreadSocketDemo ts=new ThreadSocketDemo(accept); new Thread(ts).start(); // ss.close(); } } }
package com.study.socketDemo9; import java.io.*; import java.net.Socket; import java.util.UUID; public class ThreadSocketDemo implements Runnable{ private Socket acceptSocket; public ThreadSocketDemo(Socket accept) { this.acceptSocket=accept; } @Override public void run() { BufferedOutputStream bos=null; try { //获取网络流 BufferedInputStream bis=new BufferedInputStream(acceptSocket.getInputStream()); //本地的io流把数据写到本地中,实现永久化存储 bos=new BufferedOutputStream(new FileOutputStream("D:\\Desktop\\Develop\\Study3" + "\\socketmodule\\page\\ "+ UUID.randomUUID().toString()+".png")); int b; while ((b= bis.read())!=-1){ bos.write(b); } BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(acceptSocket.getOutputStream())); bw.write("上传成功"); bw.newLine(); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (acceptSocket !=null){ try { acceptSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
服务器优化
加入多线程以后又引发了一个问题:使用多线程虽然可以让服务器同时处理多个客户端请求。但是资源消耗太大
改进方式:加入线程池
package com.study.socketThreadDemo; import com.study.socketDemo9.ThreadSocketDemo; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /* 客户端:数据来自于本地文件,接收服务器反馈 服务器:接收到的数据写入本地文件,给出反馈 - 案例分析 - 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束 - 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后。使用输出流给客户端反馈信息 - 客户端接受服务端的回馈信息 */ public class ServiceDemo { public static void main(String[] args) throws IOException { ServerSocket ss=new ServerSocket(10000); //使用线程池减少服务器资源消耗 ThreadPoolExecutor pool=new ThreadPoolExecutor( 3,//核心线程数量 10,//线程池的总数量 60,//临时线程空闲时间 TimeUnit.SECONDS,//临时线程空闲时间单位 new ArrayBlockingQueue<>(5),//阻塞队列 Executors.defaultThreadFactory(),//创建线程的默认方式 new ThreadPoolExecutor.AbortPolicy()//拒绝策略 ); //加上while循环进行服务器优化,能使多个客户端获取 while (true) { Socket accept = ss.accept(); ThreadSocketDemo ts=new ThreadSocketDemo(accept); // new Thread(ts).start(); //线程池 pool.submit(ts); // ss.close(); } } }
八、日志技术
特点:
1.通过使用日志技术,我们可以控制日志信息输送的目的地是控制台、文件等位置
2.我们也可以控制每一条日志的输出格式
3.通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
4.最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用代码
基本使用
package com.study.logdemo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Scanner; public class LogDemo { //获取logger对象 private static final Logger LOGGER=LoggerFactory.getLogger(Logger.class); public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入您的姓名:"); String name= sc.nextLine(); LOGGER.info("用户输入姓名为"+name); System.out.println("请输入您的年龄:"); String age= sc.nextLine(); try { int ageInt = Integer.parseInt(age); LOGGER.info("用户输入的年龄格式正确"+age); }catch (NumberFormatException e){ LOGGER.info("用户输入的年龄格式错误:"+age); } } }
日志技术
1.如果系统上线后只想记录一些错误信息或者不想记录日志了怎么办?
可以通过设置日志的输出级别来控制哪些日志信息输出或者不输出
日志的六种级别
级别程度依次是:TRACE<DEBUG<INFO<WARN<ERROR<FATAL
默认级别是debug
作用:将开发中不同的日志信息进行分类,只输出大于等于该级别的日志信息
ALL和OFF分别是打开全部日志信息,及关闭全部日志信息
九、枚举
为了间接的表示一些固定的值,java就给我们提供了枚举
枚举的特点
1.所有枚举类都是Enum的子类
2.我们可以通过“枚举类名.枚举项名称”去访问指定的枚举项
3.每一个枚举项其实就是该枚举的一个对象
4.枚举也是一个类,也可以去定义成员变量
5.枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的 东西,这个分号就不能省略。建议不要省略
6.枚举类可以有构造器,但是必须是private的,他默认的也是private
7.枚举类也可以有抽象方法,但是枚举项必须重写该方法
枚举的方法
package com.study.EnumDemo2; public class EnumDemo2 { public static void main(String[] args) { /* | ----------------------------------- | String name() | 获取枚举项的名称 | int ordinal() | 返回枚举项在枚举类中的索引值 | int compareTo(E o) | 比较两个枚举项,返回的是索引值的差值 | | String toString() | 返回枚举常量的名称 | static <T> T valueOf(Class<T> type,String name) | 获取指定枚举类中的指定名称的枚举值 | | values() | 获得所有的枚举项 */ //String name() | 获取枚举项的名称 String name=Season.SPRING.name(); System.out.println(name); //| int ordinal() | 返回枚举项在枚举类中的索引值 int index1=Season.SPRING.ordinal(); int index2=Season.SUMMER.ordinal(); int index3=Season.AUTUMN.ordinal(); int index4=Season.WINTER.ordinal(); System.out.println(index1); System.out.println(index2); System.out.println(index3); System.out.println(index4); // | int compareTo(E o) | 比较两个枚举项,返回的是索引值的差值 | int result = Season.SPRING.compareTo(Season.WINTER); System.out.println(result); // | String toString() | 返回枚举常量的名称 String s = Season.SPRING.toString(); System.out.println(s); // | static <T> T valueOf(Class<T> type,String name) | 获取指定枚举类中的指定名称的枚举值 Season spring = Enum.valueOf(Season.class, "SPRING"); System.out.println(spring); System.out.println(Season.SPRING == spring); // | values() | 获得所有的枚举项 Season[] values = Season.values(); for (Season value : values) { System.out.println(value); } } }
十、类加载器
作用:负责将.class文件(存储的物理文件)加载在到内存中
类加载时机
1.创建类的实例(对象)
2.调用类的类方法
3.访问类或者接口的类变量,或者为该类变量赋值
4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5.初始化某个类的子类
6.直接使用java.exe命令来运行某个主类
类加载器的分类
启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器
平台类加载器(Platform ClassLoader):负责加载JDK中一些特殊的模块
系统类加载器(System ClassLoader): 负责加载用户类路径上所指定的类库
package com.study.classLoaderDemo; public class ClassLoaderDemo1 { public static final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader(); public static void main(String[] args) { //双亲委派模型 //获得系统类加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); //获得平台类加载器 ClassLoader parent1 = systemClassLoader.getParent(); //获得启动类加载器 ClassLoader parent2 = parent1.getParent(); System.out.println("系统类加载器"+systemClassLoader); System.out.println("平台类加载器"+parent1); System.out.println("启动类加载器"+parent2); } }
类加载器的两个方法
package com.study.classLoaderDemo; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class ClassLoaderDemo2 { public static void main(String[] args) throws IOException { //加载某一个资源文件 //InputStream getResourceAsStream(String name) //获取系统类加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); //利用加载器去加载一个指定文件 //参数文件的路径 //返回值:字节流 //输入流获取文件中的资源 InputStream is=systemClassLoader.getResourceAsStream("prop.properties"); //创建对象 Properties prop=new Properties(); //获取对象的数据 prop.load(is); System.out.println(prop); is.close(); } }
类加载的过程:加载、验证、准备、解析、初始化
加载:通过包名+类名,获取这个类,准备用流进行传输,在这个类加载到内存中,加载完毕后创建一个class对象(用来存储类中的内存中的信息)
验证:衔接阶段的第一步,这一阶段为了确保class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全,也就是查看文件中的信息是否符合虚拟机规范并且有没有安全隐患
准备:负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值。
解析:将类的二进制数据流中的符号引用替换为直接引用,即本类中如果用到 了其他类,此时就需要找到对应的类。
初始化:根据程序员通过程序制定的主观计划去初始化类变量和其他资源。
小结:
当一个类被使用的时候,才会加载到内存
类加载的过程包括:加载、验证、准备、解析、初始化
十一、反射
java反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性方法;
对于任意一个对象,都能调用它的任意方法和属性
这种动态获取信息以及动态调用对象方法的功能称之为java语言的反射机制
也就是利用反射可以无视修饰符获取类里面所有的属性和方法。先获取配置文件中的信息,动态获取信息并创建对象和调用方法
用反射创建对象、反射调用成员变量、反射调用成员方法、利用反射调用他类中的属性和方法时,无视修饰符(private、public)
反射获取Class类的对象
Class.forName("全类名")
类名.class
对象.getClass();
public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException { /* .Class类中获取对象的三种方法 */ //1.Class类中的静态方法forName("全类名") Class aClass = Class.forName("com.study.myreflect.Student"); System.out.println(aClass); //2.通过class属性来获取 Class aClass1=Student.class; System.out.println(aClass1); //3.利用对象的getClass方法来获取class对象 //getClass方法是定义在object类中 Student s=new Student(); Class aClass2 = s.getClass(); System.out.println(aClass2); } }
Class类获取构造方法对象的方法
方法介绍
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) |
获取Constructor对象并获取对象
| T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
| setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
标签:java,String,枚举,服务器,new,import,日志,public,加载 From: https://www.cnblogs.com/linwenguan/p/16797194.html