文章目录
前言
java基础(Java SE)。【自用】
在线中文文档
JavaSE(一)
JavaSE(二)
一、网络相关
1.InetAddress类
- getLocalHost:获取本机InetAddress对象
- getByName:根据指定主机名/域名获取ip地址对象
- getHostName:获取InetAddress对象的主机名
- getHostAddress:获取InetAddress对象的地址
public class INetAddress_ {
public static void main(String[] args) throws UnknownHostException {
// 1.获取本机INetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
// 2.根据指定主机名获取ip地址对象
InetAddress byName = InetAddress.getByName("DESKTOP-KQI5QCM");
System.out.println(byName);
// 3.根据指定主机名/域名获取ip地址对象
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
// 4.获取INetAddress对象的主机名
String hostName = byName1.getHostName();
System.out.println(hostName);
// 5.获取INetAddress对象的地址
String hostAddress = byName1.getHostAddress();
System.out.println(hostAddress);
}
}
2.Socket
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点。
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
3.TCP相关
3.1 TCP字节流编程
public class SocketTCP01Server { // 服务器端
public static void main(String[] args) throws IOException {
// 1.开启监听,9999端口并没有被占用
ServerSocket serverSocket = new ServerSocket(9999);
// 2.等待连接
Socket accept = serverSocket.accept();
// 3.获取输入字节流
InputStream inputStream = accept.getInputStream();
byte[] res = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(res)) != -1){
System.out.println(new String(res,0,readLen));
}
// 4.获取输出字节流
OutputStream outputStream = accept.getOutputStream();
outputStream.write("hello client".getBytes());
accept.shutdownOutput();// 设置结束标记
// 5.关闭流和socket
outputStream.close();
inputStream.close();
accept.close();
serverSocket.close();
}
}
public class SocketTCP01Client { // 客户端
public static void main(String[] args) throws IOException {
// 1.连接服务器(ip,端口)
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
// 2.获取输出字节流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello server".getBytes());
socket.shutdownOutput();// 设置结束标记
// 3.获取输入字节流
InputStream inputStream = socket.getInputStream();
byte[] res = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(res)) != -1){
System.out.println(new String(res,0,readLen));
}
// 4.关闭流和socket
inputStream.close();
outputStream.close();
socket.close();
}
}
3.2 TCP字符流编程
public class SocketTCP02Server { // 服务器端
public static void main(String[] args) throws IOException {
// 1.开启监听,9999端口并没有被占用
ServerSocket serverSocket = new ServerSocket(9999);
// 2.等待连接
Socket accept = serverSocket.accept();
// 3.获取输入字节流转为字符流
InputStream inputStream = accept.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
// 4.获取输出字节流转为字符流
OutputStream outputStream = accept.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello client");
bufferedWriter.newLine();
bufferedWriter.flush();
// 5.关闭流和socket
bufferedReader.close();
bufferedWriter.close();
accept.close();
serverSocket.close();
}
}
public class SocketTCP02Client { // 客户端
public static void main(String[] args) throws IOException {
// 1.连接服务器(ip,端口)
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
// 2.获取输出字节流转为字符流
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello server");
bufferedWriter.newLine();// 换行符,表示写入的内容结束 注意:要求对方使用readLine()
bufferedWriter.flush();// 需要刷新,否则数据不会写入数据通道
// 3.获取输入字节流转为字符流
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
// 4.关闭流和socket
bufferedWriter.close();
bufferedReader.close();
socket.close();
}
}
3.3 网络上传文件
public class TCPFileUploadServer { // 服务器端
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bis);
String filePath = "G:\\aaa.jpg";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
bos.write(bytes);
bos.close();
// 获取字符流回复信息
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
writer.write("收到文件");
writer.flush();
accept.shutdownOutput();
bis.close();
accept.close();
serverSocket.close();
writer.close();
}
}
public class TCPFileUploadClient { // 客户端
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
String filePath = "C:\\Users\\hw\\Desktop\\背景1.jpg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
byte[] bytes = StreamUtils.streamToByteArray(bis); // 文件内容
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);
bis.close();
socket.shutdownOutput();
// 接受服务端的消息
InputStream inputStream = socket.getInputStream();
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);
bos.close();
socket.close();
inputStream.close();
}
}
public class StreamUtils { //工具类
/**
* @description: 将输入流转换成byte[],即把文件内容读到byte[]
* @Param is: InputStream主类
* @return: byte[]
*/
public static byte[] streamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1){
bos.write(b,0,len);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
/**
* @description: 将输入流转为String
* @Param is: InputStream主类
* @return: java.lang.String
*/
public static String streamToString(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null){
stringBuilder.append(line + "\r\n");
}
return stringBuilder.toString();
}
}
4.UDP相关
- 没有明确的服务端和客户端,演变成数据的发送端和接收端。
- 接收数据和发送数据是通过DatagramSocket对象完成。
- 将数据封装到DatagramPacket对象,发送。
- 当接收到DatagramPacket对象,需要进行拆包,取出数据。
- DatagramSocket可以指定在哪个端口接收数据。
public class UDPReceiverA {
public static void main(String[] args) throws IOException { // 服务器端
// 1.创建一个DatagramSocket对象
DatagramSocket datagramSocket = new DatagramSocket(9999);
byte[] bytes = new byte[64 * 1024];
// 2.构建一个DatagramPacket对象
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
// 3.调用接收方法,把通过网络传输的DatagramPacket对象填充进去
datagramSocket.receive(packet);
// 4.拆包取出数据并显示
int length = packet.getLength();
byte[] data = packet.getData();
String string = new String(data, 0, length);
System.out.println(string);
// 回复
data = "好的,收到了。".getBytes();
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.116"), 9998);
datagramSocket.send(packet);
// 5.关闭资源
datagramSocket.close();
}
}
public class UDPSenderB {
public static void main(String[] args) throws IOException { // 客户端
// 1.创建DatagramSocket对象,准备发送和接收数据
DatagramSocket datagramSocket = new DatagramSocket(9998);
// 2.将发送的数据封装到DatagramPacket对象
byte[] bytes = "你好啊".getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.0.116"), 9999);
datagramSocket.send(packet);
// 接收A端的数据
byte[] res = new byte[64 * 1024];
packet = new DatagramPacket(res, res.length);
datagramSocket.receive(packet);
// 拆包取出数据并显示
int length = packet.getLength();
byte[] data = packet.getData();
String string = new String(data, 0, length);
System.out.println(string);
datagramSocket.close();
}
}
5.TCP下载文件
public class TCPServer {
public static void main(String[] args) throws IOException {
// 1.建立监听且获取文件名
ServerSocket serverSocket = new ServerSocket(9999);
Socket accept = serverSocket.accept();
InputStream inputStream = accept.getInputStream();
byte[] b = new byte[1024];
int len = 0;
String fileName = "";
while ((len = inputStream.read(b)) != -1){
fileName += new String(b,0,len);
}
System.out.println("下载的文件名:" + fileName);
String resFileName = "";
if ("嘻嘻嘻".equals(fileName)){
resFileName = "G://国家地图.jpg";
}else{
resFileName = "G://国家地图.jpg";
}
// 2.读取文件数据
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(resFileName));
// 3.发送文件数据
byte[] bytes = StreamUtils.streamToByteArray(stream);
BufferedOutputStream bos = new BufferedOutputStream(accept.getOutputStream());
bos.write(bytes);
accept.shutdownOutput();
// 4.关闭资源
stream.close();
inputStream.close();
accept.close();
serverSocket.close();
bos.close();
}
}
public class TCPClient {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入下载文件名:");
String next = scanner.next();
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
OutputStream outputStream = socket.getOutputStream();
outputStream.write(next.getBytes());
socket.shutdownOutput();
// 接收文件数据
BufferedInputStream bos = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bos);
// 写入磁盘
String filePath = "G:\\" + "xxx" + next;
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(filePath));
stream.write(bytes);
// 关闭资源
bos.close();
stream.close();
outputStream.close();
socket.close();
}
}
public class StreamUtils { //工具类
/**
* @description: 将输入流转换成byte[],即把文件内容读到byte[]
* @Param is: InputStream主类
* @return: byte[]
*/
public static byte[] streamToByteArray(InputStream is) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1){
bos.write(b,0,len);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
/**
* @description: 将输入流转为String
* @Param is: InputStream主类
* @return: java.lang.String
*/
public static String streamToString(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null){
stringBuilder.append(line + "\r\n");
}
return stringBuilder.toString();
}
}
6.反射
6.1 反射机制
- 反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量、构造器、成员方法等),并能操作对象的属性及方法。【反射在设计模式和框架底层都会用到。】
- 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。
public class Reflection01 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\reflects\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
// 1.加载类,返回Class类型的对象
Class<?> cls = Class.forName(classfullpath);
// 2.通过 cls 得到加载的类对象的实例
Object o = cls.newInstance();
// 3.通过 cls 得到加载的类的methodName "hi" 的方法对象
Method method = cls.getMethod(methodName);
// 4.通过 method 调用方法
method.invoke(o);
// java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量。
// getField 不能得到私有的属性
Field name = cls.getField("name");
System.out.println(name);
// 得到name的值
System.out.println(name.get(o));
// java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示某个类的构造器。
// 得到无参构造器
Constructor constructor = cls.getConstructor();
// 得到有参构造器
Constructor constructor1 = cls.getConstructor(String.class);
// 反射优化:关闭访问检查
method.setAccessible(true);
}
}
class Cat{
public String name = "tom";
public void hi(){
System.out.println("你好 " + name);
}
public Cat(String name){
this.name = name;
}
public Cat(){
}
}
6.2 Class类
- Class也是类,因此也继承Object类。
- Class类对象不是new出来的,而是系统创建的。
- 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次。
- 每个类的实例都会记得自己是由哪个Class实例所生成。
- 通过Class可以完整的得到一个类的完整结构。
- Class对象是存放在堆的。
- 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括 方法代码,变量名,方法名,访问权限等)。
public class Class01 {
public static void main(String[] args) throws Exception {
String classAllPath = "reflects.Car";
// 获取Car 对应的 Class对象
// <?> 表示不确定的Java类型
Class<?> cls = Class.forName(classAllPath);
System.out.println(cls);
// 1.得到包名
System.out.println(cls.getPackage().getName());
// 2.得到全类名
System.out.println(cls.getName());
// 3.通过 cls 创建对象实例
Car car = (Car) cls.newInstance();
System.out.println(car);
// 4.通过 cls 获取反射获取属性 brand(私有属性不行)
Field brand = cls.getField("brand");
System.out.println(brand.get(car));
// 5.通过反射给属性赋值
brand.set(car,"奔驰");
System.out.println(brand.get(car));
// 6.得到所有属性(字段)
Field[] fields = cls.getFields();
for (Field item: fields) {
System.out.println(item.getName());
}
}
}
class Car{
public String brand = "宝马";
public int price = 5000000;
public String color = "白色";
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
", color='" + color + '\'' +
'}';
}
}
6.3 获取Class类对象的方式
public class GetClass {
public static void main(String[] args) throws Exception {
// 获取Class类对象六种方式
/** 1.
* 前提:已知一个类的全类名且该类在类路径下,可通过Class类的静态方法forName()获取,
* 可能抛出ClassNotFoundException。
*
* 应用场景:多用于配置文件,读取类全路径,加载类。
*
* 实例:Class cls = Class.forName("java.lang.cat");
*/
Class<?> cls1 = Class.forName("reflects.Dog");
/** 2.
* 前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高。
*
* 应用场景:多用于参数传递,比如通过反射得到对应构造器对象。
*
* 实例:Class cls = Cat.class;
*/
Class<Dog> cls2 = Dog.class;
/** 3.
* 前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象。
*
* 应用场景:通过创建好的对象,获取Class对象。
*
* 实例:Class cls = 对象.getClass();
*/
Dog dog = new Dog();
Class<? extends Dog> cls3 = dog.getClass();
/** 4.
* 通过类加载器[4种]来获取到类的Class对象
*
*/
ClassLoader classLoader = dog.getClass().getClassLoader();
Class<?> cls4 = classLoader.loadClass("reflects.Dog");
/** 5.
* 基本数据(int,char,boolean,float,double,byte,long,short)
* 按如下方式得到Class对象
*
* Class cls = 基本数据类型.class;
*/
Class<Integer> cls5 = int.class;
/** 6.
* 基本数据类型对应的包装类,可以通过 .type 得到Class类对象
*
* Class cls = 包装类.TYPE;
*/
Class<Integer> cls6 = Integer.TYPE;
}
}
class Dog{
public String name = "tom";
}
6.4 类加载(5个阶段)
静态加载:编译时加载相关的类,如果没有则报错,依赖性太强。
动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性。
- 加载阶段:JVM在该阶段主要目的是将字节码从不同的数据源(可能是class文件、jar包、网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象。
- 连接阶段-验证:目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。包括:文件格式验证、元数据验证、字节码验证和符号引用验证。可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
- 连接阶段-准备:JVM会在该阶段对静态变量分配内存并初始化。这些变量所使用的内存都将在方法区中进行分配。
- 连接阶段-解析:虚拟机将常量池内的符号引用替换为直接引用的过程。
- 初始化:到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行()方法的过程。()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。虚拟机会保证一个类的()方法在多线程环境中被正确的加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都需要阻塞等待,直到活动线程执行()方法完毕。
6.5 反射获取类的结构信息
- java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象。
- java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法。
- java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量。
- java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示某个类的构造器。
6.5.1 Class
- getName:获取全类名
- getSimpleName:获取简单类名
- getFields:获取所有public修饰的属性,包含本类以及父类
- getDeclaredFields:获取本类中所有属性
- getMethods:获取所有public修饰的方法,包含本类以及父类
- getDeclaredMethods:获取本类中所有方法
- getConstructors:获取所有public修饰的构造器
- getDeclaredConstructors:获取本类中所有构造器
- getPackage:以Package形式返回包信息
- getSuperClass:以Class形式返回父类信息
- getInterfaces:以Class[]形式返回接口信息
- getAnnotations:以Annotation[]形式返回注解信息
public class ReflectionUtils {
public static void main(String[] args) {
}
@Test
public void api_01() throws Exception {
// 获取Class类对象
Class<?> cls = Class.forName("reflects.Person");
// 1. getName:获取全类名
System.out.println(cls.getName());
// 2. getSimpleName:获取简单类名
System.out.println(cls.getSimpleName());
// 3. getFields:获取所有public修饰的属性,包含本类以及父类
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 4. getDeclaredFields:获取本类中所有属性
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
// 5. getMethods:获取所有public修饰的方法,包含本类以及父类
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
// 6. getDeclaredMethods:获取本类中所有方法
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod.getName());
}
// 7. getConstructors:获取所有public修饰的构造器
Constructor<?>[] constructors = cls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName());
}
// 8. getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.getName());
}
// 9. getPackage:以Package形式返回包信息
Package aPackage = cls.getPackage();
System.out.println(aPackage);
// 10. getSuperClass:以Class形式返回父类信息
Class<?> superclass = cls.getSuperclass();
System.out.println(superclass);
// 11. getInterfaces:以Class[]形式返回接口信息
Class<?>[] interfaces = cls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface.getName());
}
// 12. getAnnotations:以Annotation[]形式返回注解信息
Annotation[] annotations = cls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
interface IA{
}
class A{
public String hobby;
public A() {}
public A(String hobby) {
this.hobby = hobby;
}
public void hi(){}
}
class Person extends A implements IA{
public String name;
protected int age;
String job;
private double sal;
public Person() {
}
public Person(String name, int age, String job, double sal) {
this.name = name;
this.age = age;
this.job = job;
this.sal = sal;
}
public void m1(){
}
protected void m2(){
}
void m3(){
}
private void m4(){
}
}
6.5.2 Field
- getModifiers:以int形式返回修饰符[0:默认修饰符,1:public,2:private,4:protected,8:static,16:final]
- getType:以Class形式返回类型
- getName:返回属性名
@Test
public void api_02() throws Exception{
// 获取Class类对象
Class<?> cls = Class.forName("reflects.Person");
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
// 1. getModifiers:以int形式返回修饰符
System.out.println(declaredField.getModifiers());
// 2. getType:以Class形式返回类型
System.out.println(declaredField.getType());
// 3. getName:返回属性名
System.out.println(declaredField.getName());
}
}
6.5.3 Method
- getModifiers:以int形式返回修饰符
- getReturnType:以Class形式获取返回类型
- getName:返回方法名
- getParameterTypes:以Class[]返回参数类型数组
@Test
public void api_03() throws Exception{
// 获取Class类对象
Class<?> cls = Class.forName("reflects.Person");
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
// 1. getModifiers:以int形式返回修饰符
System.out.println(declaredMethod.getModifiers());
// 2. getReturnType:以Class形式获取返回类型
System.out.println(declaredMethod.getReturnType());
// 3. getName:返回方法名
System.out.println(declaredMethod.getName());
// 4. getParameterTypes:以Class[]返回参数类型数组
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType);
}
}
}
6.5.4 Constructor
- getModifiers:以int形式返回修饰符
- getName:返回构造器名
- getParameterTypes:以Class[]返回参数类型数组
@Test
public void api_04() throws Exception{
// 获取Class类对象
Class<?> cls = Class.forName("reflects.Person");
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor<?> dc : declaredConstructors) {
// 1. getModifiers:以int形式返回修饰符
System.out.println(dc.getModifiers());
// 2. getName:返回构造器名
System.out.println(dc.getName());
// 3. getParameterTypes:以Class[]返回参数类型数组
Class<?>[] parameterTypes = dc.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType);
}
}
}
6.6 反射实例操作
6.6.1 反射创建实例
- 调用类中的public修饰的无参构造器
- 调用类中的指定构造器
- Class类相关方法:newInstance:调用类中的无参构造器,获取对应类的对象;getConstructor(Class…clazz):根据参数列表,获取对应的public构造器对象;getDecalaredConstructor(Class…clazz):根据参数列表,获取对应的所有构造器对象
- Constructor类相关方法:setAccessible:爆破;newInstance(Object…obj):调用构造器
public class ReflectCreateInstance {
public static void main(String[] args) throws Exception {
// 获取User类的Class对象
Class<?> cls = Class.forName("reflects.User");
// 1.通过public的无参构造器创建实例
Object o = cls.newInstance();
System.out.println(o);
// 2.通过public的有参构造器创建实例
Constructor<?> constructor = cls.getConstructor(String.class);
Object jack = constructor.newInstance("jack");
System.out.println(jack);
// 3.通过非public的有参构造器创建实例
Constructor<?> constructor1 = cls.getDeclaredConstructor(int.class, String.class);
constructor1.setAccessible(true);// 爆破,使用反射可以访问私有的构造器/方法/属性
Object xxx = constructor1.newInstance(100, "xxx");
System.out.println(xxx);
}
}
class User{
private int age = 10;
private String name = "tom";
public User() {
}
public User(String name) {
this.name = name;
}
private User(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
6.6.2 反射操作属性
- 根据属性名获取Field对象 Field f = clazz对象.getDeclaredField(属性名);
- 爆破:f.setAccessible(true);
- 访问f.set(o,值); syso(f.get(o));
- 如果是静态属性,则set和get中的参数o,可以写成null。
public class ReflectAccessProperty {
public static void main(String[] args) throws Exception {
// 获取User类的Class对象
Class<?> cls = Class.forName("reflects.Student");
// 创建对象
Object o = cls.newInstance();
// 1.使用反射得到 age 属性对象
Field age = cls.getField("age");
age.set(o,88);
System.out.println(o);
// 2.使用反射操作 name 属性
Field name = cls.getDeclaredField("name");
name.setAccessible(true);// 爆破,可以操作private属性
name.set(o,"jack"); // name.set(null,"jack");也行,因为name是static
System.out.println(o);
System.out.println(name.get(o));
}
}
class Student{
public int age = 10;
private static String name = "tom";
public Student(){}
@Override
public String toString() {
return "Student{" +
"age=" + age +"name=" + name +
'}';
}
}
6.6.3 反射操作方法
- 根据方法名和参数列表获取Method方法对象:Method m = clazz对象.getDeclaredMethod(方法名,XX.class);
- 获取对象:Object o = clazz.newInstance();
- 爆破:m.setAccessible(true);
- 访问:Object returnValue = m.invoke(o,实参列表);
public class ReflectAccessMethod {
public static void main(String[] args) throws Exception {
// 获取User类的Class对象
Class<?> cls = Class.forName("reflects.Boss");
// 创建对象
Object o = cls.newInstance();
// 1.调用public的hi方法
Method hi = cls.getMethod("hi",String.class);
hi.invoke(o,"你好啊");
// 2.调用private static 的say方法
Method say = cls.getDeclaredMethod("say", int.class, String.class, char.class);
say.setAccessible(true); // 爆破
Object invoke = say.invoke(o, 12, "啊这", 'H');
System.out.println(invoke);
// 静态方法,也可以这样调用,传入null
say.invoke(null,13,"这啊",'W');
// 反射中,如果方法有返回值,统一返回Object
}
}
class Boss{
public int age = 10;
private static String name = "tom";
public Boss(){}
private static String say(int n, String s, char c){
return n + " " + s + " " + c;
}
public void hi(String s){
System.out.println("hi " + s);
}
}