46、Java编程中的Native方法、this关键字及Swing框架介绍

Java编程中的Native方法、this关键字及Swing框架介绍

1. Native方法

在Java编程中,虽然不常见,但有时你可能希望调用用非Java语言编写的子程序,这些子程序通常以本地代码的形式存在,也就是适用于你当前CPU和运行环境的可执行代码。例如,为了获得更快的执行时间,或者使用一些专门的第三方库(如统计软件包)。

然而,Java程序编译成字节码后,由Java运行时系统解释(或即时编译)执行,看起来似乎无法在Java程序中调用本地代码子程序。但实际上,Java提供了 native 关键字来声明本地代码方法。声明后,就可以像调用其他Java方法一样在Java程序中调用这些本地方法。

声明本地方法时,在方法前添加 native 修饰符,但不需要定义方法体。示例代码如下:

public native int meth();

声明本地方法后,需要提供本地方法的具体实现,并遵循一系列复杂的步骤将其与Java代码链接起来。

2. this() 关键字的使用

在Java中, this() 这种形式可以让一个构造函数调用同一个类中的另一个构造函数。其一般形式为:

this(arg-list)

当执行 this() 时,会先执行与 arg-list 参数列表匹配的重载构造函数。然后,如果原构造函数中有其他语句,再继续执行这些语句。需要注意的是, this() 调用必须是构造函数中的第一条语句。

以下是一个简单的示例:

class MyClass {
    int a;
    int b;

    // Initialize a and b individually.
    MyClass(int i, int j) {
        a = i;
        b = j;
    }

    // Use this() to initialize a and b to the same value.
    MyClass(int i) {
        this(i, i); // invokes MyClass(i, i)
    }
}

MyClass 类中,只有第一个构造函数会实际为 a b 赋值,第二个构造函数只是调用了第一个构造函数。当执行以下语句时:

MyClass mc = new MyClass(8);

调用 MyClass(8) 会导致 this(8, 8) 被执行,进而转化为对 MyClass(8, 8) 的调用。

通过 this() 调用重载构造函数可以避免代码的不必要重复,但需要注意的是,调用 this() 的构造函数执行速度会比包含内联初始化代码的构造函数稍慢,因为调用和返回机制会增加额外的开销。如果类需要创建大量对象,就需要仔细权衡代码简洁性和对象创建时间的关系。

使用 this() 还有两个限制:
- 不能在 this() 调用中使用构造函数所在类的任何实例变量。
- 不能在同一个构造函数中同时使用 super() this() ,因为它们都必须是构造函数中的第一条语句。

3. 相关问题与挑战

以下是一些相关的问题及挑战,可用于进一步巩固和拓展知识:
1. 当小程序首次开始运行时会调用什么方法?当小程序从系统中移除时会调用什么方法?
2. 解释为什么小程序如果需要持续运行就必须使用多线程。
3. 增强 Try This 15 - 1 ,使其显示作为参数传递给它的字符串,并添加第二个参数指定每次旋转之间的时间延迟(以毫秒为单位)。
4. 额外挑战:创建一个小程序,每秒更新一次并显示当前时间。可以使用 java.util 包中的 Calendar 对象来获取当前时间。
5. 简要解释Java的委托事件模型。
6. 事件监听器必须向事件源注册自己吗?
7. 额外挑战:使用 Graphics 类的 drawLine() 方法编写一个程序来跟踪鼠标移动。当鼠标按钮按下时,程序应绘制一条连续的线,直到鼠标按钮释放。
8. 简要描述 assert 关键字。
9. 举例说明本地方法对某些类型的程序有什么用处。
10. 额外挑战:尝试为“使用委托事件模型”部分中的 MouseEvents 小程序添加对 MouseWheelEvent 的支持。需要实现 MouseWheelListener 接口,并使用 addMouseWheelListener() 将小程序添加为该事件的监听器。

4. Swing框架简介

4.1 Swing的重要性

除了之前提到的小程序示例,大多数Java程序都是基于控制台的,即不使用图形用户界面(GUI)。虽然基于控制台的程序对于学习Java基础知识和编写某些类型的程序(如服务器端代码)很有用,但大多数实际应用程序都是基于GUI的。目前,Swing是Java中使用最广泛的GUI框架。

Swing定义了一系列类和接口,支持丰富的可视化组件,如按钮、文本字段、滚动面板、复选框、树和表格等。这些组件可以组合使用,构建强大且易于使用的图形界面。因此,所有Java程序员都应该熟悉Swing。

4.2 Swing的起源和设计理念

Swing并非Java早期就存在的,它是为了解决Java原始GUI子系统——抽象窗口工具包(AWT)的不足而出现的。AWT定义了一组基本组件,支持可用但功能有限的图形界面。AWT组件将各种可视化组件转换为相应的特定平台对等物,这意味着AWT组件的外观和感觉由平台决定,而不是Java。由于AWT组件使用本地代码资源,被称为重量级组件。

使用本地对等物导致了一些问题:
- 不同操作系统之间,组件的外观甚至行为可能不同,这威胁到了Java“一次编写,到处运行”的理念。
- 每个组件的外观和感觉是固定的,难以(或无法轻松)更改。
- 重量级组件存在一些限制,例如总是不透明的。

为了解决这些问题,1997年引入了Swing,它是Java基础类(JFC)的一部分。最初,Swing作为一个单独的库供Java 1.1使用,从Java 1.2开始,Swing(以及JFC的其他部分)被完全集成到Java中。

Swing通过两个关键特性解决了AWT组件的局限性:轻量级组件和可插拔的外观和感觉。
- 轻量级组件 :除极少数情况外,Swing组件都是轻量级的,即完全用Java编写,不依赖特定平台的对等物。轻量级组件具有高效和灵活的优点,并且每个组件的外观和感觉由Swing决定,而不是底层操作系统,这使得每个组件在所有平台上都能以一致的方式工作。
- 可插拔的外观和感觉 :由于每个Swing组件由Java代码渲染,而不是特定平台的对等物,因此可以将组件的外观和感觉与组件的逻辑分离。Java提供了一些外观和感觉,如 metal Nimbus ,其中 metal 也称为Java外观和感觉,是所有Java执行环境中都可用的平台独立外观和感觉,也是默认的外观和感觉。

Swing使用了改进版的经典模型 - 视图 - 控制器(MVC)架构,将视图和控制器组合成一个称为UI委托的逻辑实体,因此Swing的方法也被称为模型 - 委托架构或可分离模型架构。虽然在学习Swing的过程中可能不会直接使用模型或UI委托,但它们在背后起着重要作用。

4.3 Swing的组件和容器

Swing GUI由组件和容器两个关键部分组成,但这种区分主要是概念上的,因为所有容器也是组件。它们的区别在于用途:
- 组件 :通常指独立的可视化控件,如按钮、文本字段等。一般来说,Swing组件继承自 JComponent 类(四个顶级容器除外)。 JComponent 提供了所有组件共有的功能,如支持可插拔的外观和感觉,并且继承了AWT的 Container Component 类,因此Swing组件基于AWT组件并与之兼容。所有Swing组件的类都定义在 javax.swing 包中,部分组件类名如下表所示:
| 组件类名 | 说明 |
| ---- | ---- |
| JApplet | 小程序 |
| JButton | 按钮 |
| JCheckBox | 复选框 |
| JCheckBoxMenuItem | 复选框菜单项 |
| JColorChooser | 颜色选择器 |
| JComboBox | 下拉框 |
| JComponent | 组件基类 |
| JDesktopPane | 桌面面板 |
| JDialog | 对话框 |
| JEditorPane | 编辑器面板 |
| JFileChooser | 文件选择器 |
| JFormattedTextField | 格式化文本字段 |
| JFrame | 窗口 |
| JInternalFrame | 内部窗口 |
| JLabel | 标签 |
| JLayer | 层 |
| JLayeredPane | 分层面板 |
| JList | 列表 |
| JMenu | 菜单 |
| JMenuBar | 菜单栏 |
| JMenuItem | 菜单项 |
| JOptionPane | 选项面板 |
| JPanel | 面板 |
| JPasswordField | 密码字段 |
| JPopupMenu | 弹出菜单 |
| JProgressBar | 进度条 |
| JRadioButton | 单选按钮 |
| JRadioButtonMenuItem | 单选菜单项 |
| JRootPane | 根面板 |
| JScrollBar | 滚动条 |
| JScrollPane | 滚动面板 |
| JSeparator | 分隔符 |
| JSlider | 滑块 |
| JSpinner | 微调器 |
| JSplitPane | 分割面板 |
| JTabbedPane | 选项卡面板 |
| JTable | 表格 |
| JTextArea | 文本区域 |
| JTextField | 文本字段 |
| JTextPane | 文本面板 |
| JTogglebutton | 切换按钮 |
| JToolBar | 工具栏 |
| JToolTip | 工具提示 |
| JTree | 树 |
| JViewport | 视口 |
| JWindow | 窗口 |

可以看到,所有组件类名都以字母 J 开头。本章主要介绍了五个常用的Swing组件: JLabel JButton JTextField JCheckBox JList 。掌握它们的基本操作后,学习其他组件会更容易。

  • 容器 :Swing定义了两种类型的容器。
    • 顶级容器 :包括 JFrame JApplet JWindow JDialog 。这些容器不继承 JComponent ,但继承了AWT的 Component Container 类。与其他Swing组件不同,顶级容器是重量级的,是Swing组件库中的特殊情况。顶级容器必须位于包含层次结构的顶部,不能包含在其他容器中,并且每个包含层次结构都必须从顶级容器开始。其中, JFrame 常用于应用程序, JApplet 用于小程序。
    • 轻量级容器 :继承自 JComponent ,如 JPanel JScrollPane JRootPane 。轻量级容器常用于组织和管理一组相关组件,因为它可以包含在其他容器中,从而可以创建包含在外部容器中的相关控件子组。

4.4 顶级容器的面板

每个顶级容器都定义了一组面板,层次结构的顶部是 JRootPane 实例。 JRootPane 是一个轻量级容器,用于管理其他面板,还可以帮助管理可选的菜单栏。组成根面板的面板包括玻璃面板、内容面板和分层面板。
- 玻璃面板 :是顶级面板,位于所有其他面板之上并完全覆盖它们。玻璃面板可用于管理影响整个容器的鼠标事件,或在其他组件上绘制图形等。在大多数情况下,不需要直接使用玻璃面板。
- 分层面板 :允许为组件指定深度值,该值决定哪个组件覆盖另一个组件(即可以为组件指定Z顺序,但通常不需要这样做)。分层面板包含内容面板和(可选)菜单栏。虽然玻璃面板和分层面板对顶级容器的操作至关重要,但它们的许多功能是在幕后实现的。
- 内容面板 :是应用程序与顶级容器交互最多的面板,因为要添加的可视化组件都添加到内容面板中。也就是说,当向顶级容器添加组件(如按钮)时,实际上是将其添加到内容面板中。因此,内容面板包含用户与之交互的组件。

综上所述,Swing虽然包含复杂的设计概念,但使用起来很方便,它使开发程序用户界面这一通常困难的任务变得易于管理,让开发者可以专注于GUI本身,而不是实现细节。同时,虽然Swing是一个强大的GUI框架,但新的GUI框架JavaFX也已出现,它提供了更强大、更简化和灵活的方法来创建视觉上令人兴奋的GUI,未来Java程序员可能会同时使用Swing和JavaFX。

5. Swing组件的使用示例

5.1 创建简单的Swing应用程序

下面是一个简单的Swing应用程序示例,展示了如何创建一个包含按钮的窗口:

import javax.swing.*;

public class SimpleSwingApp {
    public static void main(String[] args) {
        // 创建JFrame实例
        JFrame frame = new JFrame("Simple Swing App");
        // 设置窗口关闭时的操作
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 创建JButton实例
        JButton button = new JButton("Click me");
        // 获取内容面板
        JPanel panel = new JPanel();
        // 将按钮添加到面板
        panel.add(button);
        // 将面板添加到窗口的内容面板
        frame.getContentPane().add(panel);
        // 设置窗口大小
        frame.setSize(300, 200);
        // 显示窗口
        frame.setVisible(true);
    }
}

上述代码的执行流程如下:
1. 创建 JFrame 对象,这是一个顶级容器,用于表示窗口。
2. 设置窗口关闭时的操作,这里设置为退出程序。
3. 创建 JButton 对象,即按钮组件。
4. 创建 JPanel 对象,作为轻量级容器,用于组织组件。
5. 将按钮添加到面板,再将面板添加到窗口的内容面板。
6. 设置窗口大小并显示窗口。

5.2 使用JTextField和JLabel

以下示例展示了如何使用 JTextField JLabel 组件:

import javax.swing.*;
import java.awt.*;

public class TextFieldLabelExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("TextField and Label Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        JLabel label = new JLabel("Enter your name:");
        JTextField textField = new JTextField(20);

        frame.add(label);
        frame.add(textField);

        frame.setSize(300, 100);
        frame.setVisible(true);
    }
}

这个示例的操作步骤如下:
1. 创建 JFrame 并设置关闭操作和布局管理器。
2. 创建 JLabel 用于显示提示信息。
3. 创建 JTextField 用于用户输入,指定列数为20。
4. 将标签和文本字段添加到窗口。
5. 设置窗口大小并显示。

5.3 创建JCheckBox

下面是一个创建 JCheckBox 的示例:

import javax.swing.*;
import java.awt.*;

public class CheckBoxExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("CheckBox Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        JCheckBox checkBox = new JCheckBox("Check me");
        frame.add(checkBox);

        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

操作步骤为:
1. 创建 JFrame 并设置相关属性。
2. 创建 JCheckBox 组件。
3. 将复选框添加到窗口。
4. 设置窗口大小并显示。

5.4 使用JList

以下是使用 JList 的示例:

import javax.swing.*;
import java.awt.*;

public class ListExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("List Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        String[] items = {"Item 1", "Item 2", "Item 3", "Item 4"};
        JList<String> list = new JList<>(items);
        frame.add(list);

        frame.setSize(200, 200);
        frame.setVisible(true);
    }
}

其步骤如下:
1. 创建 JFrame 并设置属性。
2. 定义一个字符串数组作为列表项。
3. 创建 JList 并传入列表项数组。
4. 将列表添加到窗口。
5. 设置窗口大小并显示。

6. 事件处理

6.1 匿名内部类处理事件

在Swing中,可以使用匿名内部类来处理事件。以下是一个按钮点击事件处理的示例:

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AnonymousInnerClassEventExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Anonymous Inner Class Event Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        JButton button = new JButton("Click me");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(frame, "Button clicked!");
            }
        });

        frame.add(button);
        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

操作步骤:
1. 创建 JFrame JButton
2. 为按钮添加 ActionListener ,使用匿名内部类实现 actionPerformed 方法。
3. 在 actionPerformed 方法中显示消息对话框。
4. 将按钮添加到窗口,设置窗口大小并显示。

6.2 Lambda表达式处理事件

从Java 8开始,也可以使用Lambda表达式处理事件,示例如下:

import javax.swing.*;
import java.awt.event.ActionEvent;

public class LambdaEventExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Lambda Event Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        JButton button = new JButton("Click me");
        button.addActionListener((ActionEvent e) -> {
            JOptionPane.showMessageDialog(frame, "Button clicked using Lambda!");
        });

        frame.add(button);
        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

步骤如下:
1. 创建 JFrame JButton
2. 为按钮添加 ActionListener ,使用Lambda表达式实现事件处理逻辑。
3. 将按钮添加到窗口,设置窗口大小并显示。

7. Swing Applet

创建Swing Applet与创建普通Swing应用程序类似,但需要继承 JApplet 类。以下是一个简单的Swing Applet示例:

import javax.swing.*;
import java.awt.*;

public class SwingAppletExample extends JApplet {
    @Override
    public void init() {
        try {
            SwingUtilities.invokeAndWait(() -> {
                setLayout(new FlowLayout());
                JLabel label = new JLabel("This is a Swing Applet!");
                add(label);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

操作步骤:
1. 继承 JApplet 类。
2. 重写 init 方法。
3. 在 init 方法中使用 SwingUtilities.invokeAndWait 确保在事件调度线程中执行UI操作。
4. 设置布局管理器,创建 JLabel 并添加到Applet。

8. 总结

8.1 Swing的优势

  • 丰富的组件 :Swing提供了大量的可视化组件,如按钮、文本字段、复选框等,可以方便地构建各种复杂的GUI界面。
  • 可移植性 :轻量级组件使得Swing应用程序在不同平台上具有一致的外观和行为,符合Java“一次编写,到处运行”的理念。
  • 可插拔外观和感觉 :可以轻松更改组件的外观和感觉,满足不同用户的需求。
  • 事件处理机制 :支持多种事件处理方式,如匿名内部类和Lambda表达式,方便开发者处理用户交互。

8.2 与其他GUI框架的比较

虽然Swing是一个成熟且广泛使用的GUI框架,但新的JavaFX框架也有其优势。JavaFX提供了更强大、更简化和灵活的方法来创建视觉上令人兴奋的GUI,并且在动画、多媒体等方面有更好的支持。不过,由于Swing存在大量的遗留代码,在未来一段时间内,两者可能会同时存在于Java开发中。

8.3 学习建议

对于初学者来说,建议先掌握Swing的基础知识,包括组件的使用、布局管理器、事件处理等。可以通过阅读相关文档、参考示例代码和进行实践项目来逐步提高。随着对Swing的熟悉,可以进一步学习JavaFX,了解其新特性和优势,为开发更复杂的应用程序做好准备。

8.4 后续展望

随着Java技术的不断发展,GUI框架也会不断演进。未来可能会出现更高效、更易用的GUI开发方式,开发者需要持续学习和关注新技术的发展,以适应不断变化的市场需求。

以下是一个简单的Swing开发流程的mermaid流程图:

graph LR
    A[创建顶级容器] --> B[设置布局管理器]
    B --> C[创建组件]
    C --> D[添加组件到容器]
    D --> E[设置事件处理]
    E --> F[显示窗口或Applet]

总之,Swing是Java开发中一个重要的GUI框架,掌握它对于开发实际应用程序具有重要意义。同时,了解其他GUI框架的发展趋势,也有助于开发者在不同场景下做出更合适的选择。

【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究不仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换不同算法或测试系统进一步拓展研究。
先看效果: https://pan.quark.cn/s/3756295eddc9 在C#软件开发过程中,DateTimePicker组件被视为一种常见且关键的构成部分,它为用户提供了图形化的途径来选取日期与时间。 此类控件多应用于需要用户输入日期或时间数据的场景,例如日程管理、订单管理或时间记录等情境。 针对这一主题,我们将细致研究DateTimePicker的操作方法、具备的功能以及相关的C#编程理念。 DateTimePicker控件是由.NET Framework所支持的一种界面组件,适用于在Windows Forms应用程序中部署。 在构建阶段,程序员能够通过调整属性来设定其视觉形态及运作模式,诸如设定日期的显示格式、是否展现时间选项、预设的初始值等。 在执行阶段,用户能够通过点击日历图标的下拉列表来选定日期,或是在文本区域直接键入日期信息,随后按下Tab键或回车键以确认所选定的内容。 在C#语言中,DateTime结构是处理日期与时间数据的核心,而DateTimePicker控件的值则表现为DateTime类型的实例。 用户能够借助`Value`属性来读取或设定用户所选择的日期与时间。 例如,以下代码片段展示了如何为DateTimePicker设定初始的日期值:```csharpDateTimePicker dateTimePicker = new DateTimePicker();dateTimePicker.Value = DateTime.Now;```再者,DateTimePicker控件还内置了事件响应机制,比如`ValueChanged`事件,当用户修改日期或时间时会自动激活。 开发者可以注册该事件以执行特定的功能,例如进行输入验证或更新关联的数据:``...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值