【JAVA CORE_API】Day21 Map接口、在线聊天室v3.0、Java的反射机制(P1)

2024-08-24 04:04

本文主要是介绍【JAVA CORE_API】Day21 Map接口、在线聊天室v3.0、Java的反射机制(P1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Map接口

Map接口

  • Map是Java中用于存储键值对(key-value pairs)的接口,每个键(key)对应一个值(value)。它不允许重复的键,但允许不同的键映射相同的值。

  • 关键特点:

    • 键值对存储:每个key对应一个值,使用key来获取对应的值;

    • 不允许重复key:一个key只能存在一次,重复key会覆盖旧值;

    • 常用实现类:HashMapTreeMapLinkedHashMap等。

  • 常用方法:

    • put(K key, V value):插入键值对;

    • get(Object key):根据key获取对应的值;

    • remove(Object key):根据key删除对应的键值对;

    • containsKey(Object key):检查是否包含指定key;

    • keySet():返回所有key的集合。

  • Map是一个非常灵活的接口,广泛用于需要通过唯一key快速访问数据的场景。

 package Day21;import java.util.HashMap;import java.util.Map;/*** java.util.Map 查找表*/public class MapDemo1 {public static void main(String[] args) {// Map创建时要分别指定key和value的类型Map<String, Integer> map = new HashMap<>();/*put(K k, V v):返回一个value值向Map中保存一组键值对由于Map要求key不允许重复,如果使用重复的key存入新的value,那么则是替换value操作,如果此Map中不包含该key的映射关系,则返回null。此时put方法会把被替换下来的value返回。否则返回值为null。*/Integer value = map.put("语文", 100);System.out.println(value);map.put("数学", 100);map.put("外语", 100);map.put("物理", 100);map.put("化学", 100);System.out.println(map);value = map.put("语文", 66);   // 会将“语文”原本的99替换掉System.out.println(value);   // 99System.out.println(map);//        int valuePoint = map.put("语文", 100);//        System.out.println(valuePoint);  // 空指针异常System.out.println("");/*** get(Object key) 返回value类型* 根据给定的key提取对应的value* 如果给定的key在Map中不存在则返回值为null*/value = map.get("语文");System.out.println(value);value = map.get("体育");System.out.println(value);System.out.println("");/*** size(): 返回int类型* 返回Map中键值对的个数*/int size = map.size();System.out.println("size=" + size);System.out.println("");/*** remove() 返回value类型* 根据给定的key删除对应的键值对,并且会将该key对应的value返回*/value = map.remove("数学");System.out.println(value);  // 数学对应的value值:98System.out.println(map);System.out.println("");/*** isEmpty() 返回boolean类型* 检查是否为空Map(Map中不含有任何键值对)*/boolean isEmpty = map.isEmpty();System.out.println("是否为空Map" + isEmpty);System.out.println("");/*** containsKey(key) 返回boolean类型* containsValue(Value) 返回boolean类型* 判断Map中是否包含指定的key或value* 底层还是利用equals方法比较*/boolean containsKey = map.containsKey("语文");System.out.println("是否包含key:" + containsKey);boolean containsValue = map.containsValue(100);System.out.println("是否包含value:" + containsValue);System.out.println("");/*** clear()* 清空Map*/map.clear();System.out.println(map);}}

Map的遍历

常用实现类

  • 遍历<key,value>

    • 使用 entrySet() 方法,获取键值对的集合。

    • 示例:

       package Day21;import java.util.HashMap;import java.util.Map;import java.util.Set;public class MapDemo2 {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("语文", 100);map.put("数学", 90);map.put("英语", 80);map.put("化学", 100);map.put("物理", 100);System.out.println(map);/*** entrySet() 返回所有的键值对* 将当前Map中所有的键值对以若干的Entry实例表示,并将他们以一个Set集合的形式返回*/Set<Map.Entry<String, Integer>> entrySet = map.entrySet();for (Map.Entry<String, Integer> entry : entrySet) {System.out.println("entry:" + entry);}}}
  • 遍历key

    • 使用 keySet() 方法,获取键的集合。

    • 示例:

       package Day21;import java.util.HashMap;import java.util.Map;import java.util.Set;public class MapDemo2 {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("语文", 100);map.put("数学", 90);map.put("英语", 80);map.put("化学", 100);map.put("物理", 100);System.out.println(map);/*** keySet() 返回所有的key* 将当前Map中所有的key以一个Set集合的形式返回*/Set<String> keySet = map.keySet();for (String key : keySet) {System.out.println("key:" + key);}}}
  • 遍历value

    • 使用 values() 方法,获取所有值的集合。

    • 示例:

       for (V value : map.values()) {// 处理值}
      

forEach方法

  • forEach 方法

    • forEach 是 Java 8 引入的一个方法,用于遍历集合或流中的每个元素,通常与 Lambda 表达式结合使用。
  • 用法示例

     List<String> list = Arrays.asList("a", "b", "c");// 使用 forEach 方法遍历列表list.forEach(element -> {System.out.println(element);});
    
  • 关键特点

    • 简洁:用 Lambda 表达式直接在遍历时定义要执行的操作。

    • 灵活:可以传递方法引用,如 list.forEach(System.out::println);

    • 适用范围:适用于所有实现了 Iterable 接口的集合,如 ListSet,以及 Stream 流。

    • forEach 方法简化了遍历过程,特别适合在函数式编程风格中使用。

小练习

 package Day21;import java.util.HashMap;import java.util.Map;/*** 编写程序,统计字符串中每个字符出现的次数*/public class Test {public static void main(String[] args) {/*输出的结果,要求看到每个字符出现的次数。例如h:2e:2l:4xx:xx思路:1:创建一个Map用来保存统计结果key:出现的每种字符   value:该字符出现的次数2:2.1:遍历line中的每一个字符String有一个方法:charAt(int index) 根据下标提取对应的元素下标范围:0-字符串的length2.2:将该字符作为key存入到map中,这是会有两种情况Map的containsKey()方法2.2.1:如果这个字符作为key在map中不存在,将字符作为key,value存入1(第一次出现)2.2.3:如果该字符作为key在map中存在,说明该字符之前出现过,此时将value+12.3:遍历完毕相当于统计完毕,将map输出看结果即可注意:char类型对应的包装类是Character*/String line = "Patiention! Is key in life! Just be patient!";Map<Character, Integer> map = new HashMap<>();for (int i = 0; i < line.length(); i++) {char c = line.charAt(i);if (map.containsKey(c)) {map.put(c, map.get(c) + 1);} else {map.put(c, 1);}}System.out.println(map);}}

聊天室v3.0

Client.java

 package Day21;import java.io.*;import java.net.Socket;import java.nio.charset.StandardCharsets;import java.util.Scanner;/*** 客户端*/public class Client {/*** java.net.Socket:套接字* 它封装了TCP协议的通信细节,使用它可以和服务器建立连接并进行交互* 可以理解为是电话*/private Socket socket;public Client() {// 实例化Socket对象,就是与远端计算机建立连接的过程// 需要传递两个对数:// 1.远端计算机的IP地址,用于找到网络上对方的计算机// 2.远端计算机的端口号,用于找到对方计算机中的应用程序try {System.out.println("正在连接服务端......");/**实例化Socket对象,就是与远端计算机建立连接的过程需要传入两个对数:1.服务端的IP地址,用于找到网络上对方的计算机2.服务端口,用于找到服务端计算机上的应用程序查看IP操作:Windows: win+r,输入cmd,回车,输入ipconfig,IPv4就是IP地址Mac:触控板上五指向中间抓,选择"终端"程序打开,输入/sbin/ifconfig查看IP地址创建Socket对象向服务端发送请求时,会进行三次握手*/socket = new Socket("localhost", 8888);System.out.println("连接成功!");} catch (IOException e) {e.printStackTrace();}}// 该方法用于启动客户端程序的执行public void start() {/*Socket提供了一个方法:OutputStream getOutputStream()通过socket获取输出流,将写出的信息发送给服务端*/try {OutputStream outputStream = socket.getOutputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);PrintWriter printWriter = new PrintWriter(bufferedWriter,true);  // 自动行刷新// 输入昵称Scanner scanner01 = new Scanner(System.in);while (true) {System.out.println("请输入昵称:");// 要求:昵称不能为空或者只有空格都不可以,如果发生则提示用户重新输入String nickname = scanner01.nextLine();if (nickname.trim().isEmpty()){System.out.println("昵称不能为空,请重新输入!");}else {printWriter.println(nickname);System.out.println("昵称设置成功!欢迎您:" + nickname);break;}}// 启动用于读取服务端消息的线程ServerHandler serverHandler = new ServerHandler();Thread thread = new Thread(serverHandler);// 如果我们输入exit想结束聊天,这个线程依然活着,所以我们想让他和主线程一起死,于是我们设计这个线程为守护线程thread.setDaemon(true);thread.start();Scanner scanner = new Scanner(System.in);while (true) {String line = scanner.nextLine();if ("exit".equalsIgnoreCase(line)) {break;}printWriter.println(line);  // 发送消息给服务端}} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();  // 进行四次挥手} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {Client client = new Client();client.start();}// 处理回复消息,创建回复接口:该线程任务负责读取来自服务端发送过来的消息并输出到控制台上private class ServerHandler implements Runnable {@Overridepublic void run() {try {// 通过Socket提供的方法InputStream getInputStream(),获取输入流,将服务端发送的消息读取出来InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 循环读取来自服务端发送过来的消息并输出到客户端控制台上String message;while ((message = bufferedReader.readLine()) != null) {System.out.println(message);}} catch (IOException e) {e.printStackTrace();}}}}

server.java

 package Day21;import java.io.*;import java.net.ServerSocket;import java.net.Socket;import java.nio.charset.StandardCharsets;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** 服务端*/public class Server {/*** java.net.ServerSocket:* 运行在服务端,主要作用有两个:* 1.像系统申请服务端口,客户端通过该端口与服务端建立连接* 2.监听服务端口,一旦有客户链接了,就会立即创建一个Socket对象与客户端进行交互*      如果将Socket比喻为“电话”,那ServerSocket就相当于客户中心的“总机”。* 解决方法:* 1.更换端口号;* 2.杀死占用该端口的进行(通常由于服务端启动了两次导致)*/// key:用户的昵称    value:该客户端的输出流private Map<String, PrintWriter> allOut = new HashMap<>();private ServerSocket serverSocket;//    private List<PrintWriter> allOut = new ArrayList<>();public Server(){try {System.out.println("正在启动服务端......");/*** 创建ServerSocket对象时,会申请一个端口* 如果该端口被其它程序占用,会抛出异常:*   java.net.BindException: Address already in use:* 解决办法:* 1.更换端口号* 2.杀死占用该端口的进行(通常由于服务端启动两次导致)*/serverSocket = new ServerSocket(8888);System.out.println("服务端启动完成!");} catch (IOException e) {e.printStackTrace();}}// 启动服务端方法:/*** accept():* 用于接收客户端连接,并返回一个Socket对象与所连接的客户端进行交互* 该方法是一个阻塞方法,调用后程序会“卡住”,直到一个客户端连接为止*/public void start(){try {while (true){System.out.println("服务端正在等待客户端连接......");Socket socket = serverSocket.accept();System.out.println("一个客户端连接了!");// 启动单独的线程来处理与客户端的通信Runnable clientHandler = new ClientHandler(socket);Thread thread = new Thread(clientHandler);thread.start();}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {Server server = new Server();server.start();}/*** 该线程任务用于负责与指定的客户端通信*/private class ClientHandler implements Runnable{private Socket socket;private String host;  // 记录客户端的IP地址private String nickname;public ClientHandler(Socket socket) {this.socket = socket;// 通过socket获取客户端ip地址host = socket.getInetAddress().getHostAddress();}@Overridepublic void run() {PrintWriter printWriter = null;try {//接收客户端发送过来的消息/*Socket提供了一个方法:InputStream getInputStream()通过socket获取输入流,用于读取客户端发送过来的数据*/InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);// 读取客户端发送过来的第一行字符串一定是客户端的昵称nickname = bufferedReader.readLine();// 通过Socket获取输出流,用于将消息发送给该客户端OutputStream outputStream = socket.getOutputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);printWriter = new PrintWriter(bufferedWriter,true);// 将对应该客户端的输出流存入到共享集合allOut中synchronized (allOut) {allOut.put(nickname, printWriter);}// 广播该客户端上线了broadcast(nickname + "["+host+"]上线了!当前在线人数:" + allOut.size());/*当我们通过br.readLine()读取客户端发送过来的数据时,客户端如果调用socket.close()时(进行四次挥手),正常与我们断开连接那么readLine()会返回null若客户端异常中断(强制杀死进程),此时readLine()会抛出异常注意:这种情况咱们服务端是没有办法的*/String message;while ((message = bufferedReader.readLine()) != null) {    // 读取客户端发送过来的消息if(message.startsWith("@")) {// 如果消息是以@开头,说明是私聊消息sendMessageToSomeone(message);}else{broadcast(nickname + "[" +host + "]说:" + message);}}} catch (IOException e) {} finally {// 处理该客户端断开连接后的操作// 将该客户端的输出流从共享集合allOut中删除synchronized (allOut) {//                    allOut.remove(printWriter);allOut.remove(nickname);}// 广播消息,告知所有客户端该用户下线了broadcast(nickname + "[" + host + "]下线了!当前在线人数:" + allOut.size());try {    // 进行四次挥手serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}/*** 将消息发送给所有客户端* @param message*/private void broadcast(String message){System.out.println(message);synchronized (allOut) {//                for (PrintWriter writer : allOut) {//                    writer.println(message);//                }for (PrintWriter writer : allOut.values()){writer.println(message);}}}/*** 私聊功能,将消息发送给某个人* @param message*/public void sendMessageToSomeone(String message){/*过程:私聊消息的格式-->@对方昵称:聊天消息1:截取出对方的昵称substring()->截"@"到":"之间的内容2:从allOut中使用对方的昵称作为key提取到对应的输出流map.get(对方昵称)3:将聊天消息通过该输出流发送给对方聊天消息substring()->":"后面的内容然后通过输出流发送给对象*/// 首先验证私聊消息是否为正确的格式:@xxx:xxxif (message.matches("@.+:.+")) {//1String toNickName = message.substring(1, message.indexOf(":"));if (allOut.containsKey(toNickName)) {//2PrintWriter printWriter = allOut.get(toNickName);//3String toMessage = message.substring(message.indexOf(":") + 1);printWriter.println(nickname + "悄悄对你说:" + toMessage);}else {PrintWriter printWriter = allOut.get(nickname);printWriter.println("私聊对象不存在!");}} else {// 如果格式不对,给当前用户提示私聊格式不正确PrintWriter printWriter = allOut.get(nickname);printWriter.println("私聊消息格式不正确,私聊的格式应当为:@对方昵称:私聊消息");}}}}
  • 接下来将Client.java客户端内全部代码发送给GPT,请求生成一个可视化界面,GPT语言:这是一个多人在线聊天室的客户端代码,请根据Client.java中的Client类的代码内容,生成图形化的界面,对输入昵称可以单独创建界面,聊天界面要求要在窗口的下方生成文本框,用于获取用户输入的聊天消息发送给服务端,包括上方存在一个文本框用来获取服务器发送来的聊天记录信息,下方具有发送按钮,发送可以使用enter键触发,字体也可以进行修改,界面内部使用中文布局,可以参考其他在线聊天室软件的界面布局,还有就是将字的大小改为24,聊天界面按钮别搞那么长,把聊天框放大一些,把界面做的更复杂一些

     package Day21;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.io.*;import java.net.Socket;import java.nio.charset.StandardCharsets;public class ClientGUI {private Socket socket;private String nickname;private JTextArea chatArea;private JTextField inputField;public ClientGUI() {connectToServer();createNicknameFrame();}// 连接服务器private void connectToServer() {try {socket = new Socket("localhost", 8888);System.out.println("连接成功!");} catch (IOException e) {e.printStackTrace();}}// 昵称输入界面private void createNicknameFrame() {JFrame nicknameFrame = new JFrame("输入昵称");nicknameFrame.setSize(500, 250);nicknameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);nicknameFrame.setLayout(new BorderLayout());JPanel panel = new JPanel(new GridBagLayout());JLabel label = new JLabel("请输入昵称:");label.setFont(new Font("宋体", Font.PLAIN, 24));JTextField nicknameField = new JTextField(15);nicknameField.setFont(new Font("宋体", Font.PLAIN, 24));JButton confirmButton = new JButton("确认");confirmButton.setFont(new Font("宋体", Font.PLAIN, 24));confirmButton.addActionListener(e -> {String inputNickname = nicknameField.getText().trim();if (inputNickname.isEmpty()) {JOptionPane.showMessageDialog(nicknameFrame, "昵称不能为空,请重新输入!");} else {nickname = inputNickname;sendNicknameToServer();nicknameFrame.dispose();createChatFrame();}});GridBagConstraints gbc = new GridBagConstraints();gbc.insets = new Insets(10, 10, 10, 10);gbc.gridx = 0;gbc.gridy = 0;panel.add(label, gbc);gbc.gridx = 1;panel.add(nicknameField, gbc);gbc.gridx = 0;gbc.gridy = 1;gbc.gridwidth = 2;panel.add(confirmButton, gbc);nicknameFrame.add(panel, BorderLayout.CENTER);nicknameFrame.setVisible(true);}// 发送昵称给服务器private void sendNicknameToServer() {try {PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8)), true);writer.println(nickname);System.out.println("昵称设置成功!欢迎您:" + nickname);} catch (IOException e) {e.printStackTrace();}}// 主聊天界面private void createChatFrame() {JFrame chatFrame = new JFrame("聊天室 - " + nickname);chatFrame.setSize(800, 600);chatFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);chatFrame.setLayout(new BorderLayout());chatArea = new JTextArea();chatArea.setEditable(false);chatArea.setFont(new Font("宋体", Font.PLAIN, 24));JScrollPane chatScrollPane = new JScrollPane(chatArea);inputField = new JTextField();inputField.setFont(new Font("宋体", Font.PLAIN, 24));inputField.setPreferredSize(new Dimension(600, 50));JButton sendButton = new JButton("发送");sendButton.setFont(new Font("宋体", Font.PLAIN, 24));sendButton.setPreferredSize(new Dimension(150, 50));// 按下发送按钮或回车键发送消息sendButton.addActionListener(e -> sendMessage());inputField.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() == KeyEvent.VK_ENTER) {sendMessage();}}});JPanel inputPanel = new JPanel(new BorderLayout());inputPanel.add(inputField, BorderLayout.CENTER);inputPanel.add(sendButton, BorderLayout.EAST);chatFrame.add(chatScrollPane, BorderLayout.CENTER);chatFrame.add(inputPanel, BorderLayout.SOUTH);chatFrame.setVisible(true);// 启动接收服务器消息的线程new Thread(new ServerHandler()).start();}// 发送消息到服务器private void sendMessage() {String message = inputField.getText().trim();if (!message.isEmpty()) {try {PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8)), true);writer.println(message);inputField.setText("");} catch (IOException e) {e.printStackTrace();}}}// 处理服务器消息private class ServerHandler implements Runnable {@Overridepublic void run() {try {BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));String message;while ((message = reader.readLine()) != null) {chatArea.append(message + "\n");}} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {new ClientGUI();}}

在这里插入图片描述

Java的反射机制

反射机制

什么是反射机制

  • Java的反射机制是一种让程序在运行时动态获取类、接口、方法、属性等信息的能力。通过反射,程序可以在不知道类的情况下创建对象、调用方法、或访问属性。这种机制允许程序在运行时检查和操作代码结构,而不需要在编译时知道具体的类型。

  • 简而言之,反射使得代码能够“自我检查”和“自我修改”。这对于编写更灵活、通用的代码非常有用,比如框架、工具库、或一些需要处理未知类型对象的程序。

  • Java的反射机制就像是你手中的一面“魔法镜子”(反射API)。当你面对一扇门(类)时,不用打开门就能通过这面魔法镜子看到门后面的所有东西(类的结构),比如房间里的家具(属性)、开关(方法)等等。你甚至可以通过镜子直接操作这些东西,比如打开开关(调用方法)或移动家具(修改属性),而不需要知道这个房间具体是什么样的。

反射API

什么是Class类?

  • Class类是Java反射机制的核心。它是一个用来表示类或接口的字节码文件在JVM中的对象。通过Class类,程序可以在运行时获取关于类的各种信息,比如类的名称、修饰符、构造方法、方法、字段等。

  • 每个Java类在加载时,JVM都会为其生成一个对应的Class对象,这个对象包含了该类的所有元数据信息。开发者可以通过这个Class对象使用反射机制来操作这个类。

获取类对象

  • Class.forName("类的全限定名")

    • 用法: 通过类的全限定名(即包名+类名)来获取Class对象。

    • 适用场景: 当你知道类的名称,并且希望在运行时动态加载类时,这种方法最为常用。

    • 示例:

       Class class1 = Class.forName("java.util.String");
      
  • 类名.class

    • 用法: 直接通过类的名字获取Class对象。

    • 适用场景: 当你在编译时就已经知道类的具体类型时,这种方法更简洁。

    • 示例:

       String name = class1.getName();
      
  • 对象.getClass()

    • 用法: 通过一个已实例化的对象来获取它的Class对象。

    • 适用场景: 当你有一个对象的实例,但不确定它的具体类型时,这种方法可以动态获取该对象的Class对象。

    • 示例:

       String string = new String();Class class1 = string.getClass();
      

获取类信息

  • 获取类的完全限定名

    • 方法: getName()

    • 示例:

       System.out.println(class1.getName());
      
  • 获取当前类名

    • 方法getSimpleName()

    • 示例

       System.out.println(class1.getSimpleName());
      
  • 获取构造方法

    • 方法: getConstructors(), getDeclaredConstructors()

    • 示例:

       Constructor[] constructors = class1.getConstructors();for (Constructor constructor : constructors) {System.out.println("Constructor: " + constructor);}// 获取所有声明的构造方法(包括私有构造方法)Constructor[] declaredConstructors = class1.getDeclaredConstructors();for (Constructor constructor : declaredConstructors) {System.out.println("Declared Constructor: " + constructor);}
      
  • 获取方法

    • 方法: getMethods(), getDeclaredMethods()

    • 示例:

       Method[] methods = class1.getMethods();for (Method method : methods) {System.out.println("Method: " + method);}// 获取所有声明的方法(包括私有方法)Method[] declaredMethods = class1.getDeclaredMethods();for (Method method : declaredMethods) {System.out.println("Declared Method: " + method);}
      
  • 获取字段

    • 方法: getFields(), getDeclaredFields()

    • 示例:

       Field[] fields = class1.getFields();for (Field field : fields) {System.out.println("Field: " + field);}// 获取所有声明的字段(包括私有字段)Field[] declaredFields = class1.getDeclaredFields();for (Field field : declaredFields) {System.out.println("Declared Field: " + field);}
      
  • 获取父类

    • 方法: getSuperclass()

    • 示例:

       Class superClass = class1.getSuperclass();System.out.println("Superclass: " + superClass);
      
  • 获取接口

    • 方法: getInterfaces()

    • 示例:

       Class[] interfaces = class1.getInterfaces();for (Class iface : interfaces) {System.out.println("Interface: " + iface);}
      
  • 获取类加载器

    • 方法: getClassLoader()

    • 示例:

       ClassLoader classLoader = class1.getClassLoader();System.out.println("ClassLoader: " + classLoader);
      

Package类

  • java.lang.Package,用于获取包内的数据,每一个实例都用于表示一个包的信息,通过类对象的getPackage()方法获取一个类的包信息。

     Class class1 = ArrayList.class;Package pack = class1.getPackage();// 通过包对象获取它表示的包的名字String packName = pack.getName();System.out.peintln(packName);  // 输出java.util
    

对象实例化

  • 我们提前创建一个Person类,顺便将其配置好:

     package day21;import java.util.Objects;public class Person {private String name;private int age;public Person() {}public Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic boolean equals(Object object) {if (this == object) return true;if (object == null || getClass() != object.getClass()) return false;Person person = (Person) object;return age == person.age && Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}}
  • 使用 new 关键字

    • 这是最常见和直接的对象实例化方法,通过new关键字可以创建类的实例:
     // 程序写死,那么只能实例化ArrayListArrayList arrayList = new ArrayList(); 
    
    • 这种方式在编译时需要知道类的具体类型,并且只能用于类的公共无参构造函数。
  • 使用 Class 类的 newInstance() 方法

    • Class类提供了newInstance()方法来创建对象实例。这种方法允许你通过反射在运行时动态创建类的实例:

    • 方法: Class.newInstance()

    • 用法: 调用Class对象的newInstance()方法,创建一个该类的实例。

    • 示例:

               // 1.获取要实例化的类的对象// 反射机制实例化对象Scanner scanner = new Scanner(System.in);  // 反射机制可以运行起来根据需要去实例化的对象System.out.println("请输入一个类的名字:");String className = scanner.next();Class cls = Class.forName(className);/*2.类对象*/Object obj = cls.newInstance();System.out.println(obj);
      
    • 注意: newInstance()方法已被标记为过时(deprecated),主要因为它不能处理构造函数的异常。建议使用Constructor类的方法来替代。

  • 使用 Constructor

    • Constructor类提供了更灵活的方式来创建对象实例。可以通过Constructor对象调用构造函数来创建实例:

    • 获取 Constructor 对象: 使用Class类的getConstructor()getDeclaredConstructor()方法获取构造函数。

    • 创建实例: 使用Constructor对象的newInstance()方法创建对象。

    • 示例:

     package day21;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class ReflectDemo3 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Person person = new Person("张禹垚", 21);System.out.println(person);// 获取类对象Class cls = Class.forName("day21.Person");// Person(String)Constructor constructor = cls.getConstructor(String.class);// new Person("刘备");Object obj = constructor.newInstance("刘备");System.out.println(obj);Class cls1 = Class.forName("day21.Person");Constructor constructor1 = cls1.getConstructor(String.class, int.class);Object obj1 = constructor1.newInstance("关羽", 33);System.out.println(obj1);}}

这篇关于【JAVA CORE_API】Day21 Map接口、在线聊天室v3.0、Java的反射机制(P1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101394

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

电力系统中的A类在线监测装置—APView400

随着电力系统的日益复杂和人们对电能质量要求的提高,电能质量在线监测装置在电力系统中得到广泛应用。目前,市场上的在线监测装置主要分为A类和B类两种类型,A类和B类在线监测装置主要区别在于应用场景、技术参数、通讯协议和扩展性。选择时应根据实际需求和应用场景综合考虑,并定期维护和校准。电能质量在线监测装置是用于实时监测电力系统中的电能质量参数的设备。 APView400电能质量A类在线监测装置以其多核