总结
1. protected 属性的子类对象的调用问题
- 无论是否在同一个包里面, 子类都可以调用父类的protected的任意属性和方法.
- 在不同的包和不同的类里面, 子类的对象不可以访问父类的protected属性和方法.
- 一般情况下, 我们可以认为, 对于protected的修饰的属性和方法, 子类继承之后, 对于别的类来说相当于私有, 也就是在别的类中, 子类的对象不可以访问.
2. Java Constructor 的同类型参数个数的函数重载问题
- 在我做某一个项目的时候, 我使用了几个不同的构造方法, 但是属性的类型都是String类型的.
- 在我向数据库中插入的时候, 会发现数据长度问题错误.
- 仔细检查后发现是构造方法的重载问题, 使用了同样个数的参数, 但是赋值的时候, 程序只认构造方法的类型, 和个数, 类型和个数匹配后, 程序不会考虑别的, 只是一一赋值, 但是赋值的时候不一定是按照开发者的想法来进行赋值.
- 在使用构造方法时, 一定要检查参数的个数和类型是否匹配.
3. 托盘图标的创建以及移除问题
-
我们可以使用System Tray这个类来创建以及生成Java GUI Swing或者AWT的托盘图标.
-
测试代码
import java.awt.Image; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.SystemTray; import java.awt.Toolkit; import java.awt.TrayIcon; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; /** * 测试托盘区的图标问题 * * @author Master_Joe qiaoguangtong@aliyun.com * */ public class TestSystemTray extends JFrame { /** * */ private static final long serialVersionUID = 1L; private TrayIcon trayIcon; private SystemTray systemTray; private PopupMenu rightKeyJPopupMenu; private MenuItem menuItem1; public TestSystemTray() { super("System tray test"); systemTray = SystemTray.getSystemTray(); setSize(150, 150); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); try { String filePath = "resources/RegisterImages/Profiles/0_online.png"; Image image = Toolkit.getDefaultToolkit().getImage(filePath); trayIcon = new TrayIcon(image); systemTray.add(trayIcon); this.dispose(); } catch (Exception e) { e.printStackTrace(); } this.addWindowListener(new WindowAdapter() { @Override public void windowIconified(WindowEvent e) { dispose(); } }); trayIcon.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { setExtendedState(NORMAL); } setVisible(true); } }); rightKeyJPopupMenu = new PopupMenu(); menuItem1 = new MenuItem("Exit"); rightKeyJPopupMenu.add(menuItem1); trayIcon.setPopupMenu(rightKeyJPopupMenu); // trayIcon.addMouseListener(new MouseAdapter() { // // @Override // public void mousePressed(MouseEvent e) { // rightKeyJPopupMenu.setVisible(true); // } // }); } public static void main(String[] args) { new TestSystemTray(); } }
3.1 AWT的中文乱码
- 在使用托盘的弹出菜单时, 我们只能使用PopupMenu这个组件来进行设置, 但是使用这个方法会产生乱码问题
- 我的电脑时英文的System, 我的文件系统编码格式时UTF-8, 同时JVM也是UTF-8启动的, 但是使用AWT的MenuItem这个组件进行添加菜单的功能描述的时候, 在右下角的托盘图标的菜单会显示方格的乱码
- 我使用String类里面的getBytes(String charsetName) 这个方法获取了UTF-8的字符串, 没有什么用, 然后又获取了GBK的字符串, 结果换了一种新的乱码, 反正也是乱码, 然后我从网上搜索到的解决方案是在JVM的参数上加了一行**-DFile.encoding=GBK然后就好了, 但是随之而来的就是我的控制台的中文显示全部变成了乱码, 无奈, 只好使用了English**这种神奇的不会发生乱码的语言.
4. 数据库查询工具的反射问题
-
我在数据库查询的时候使用了Apache的DbUtils工具, 使用QueryRunner类来进行查询
-
使用QueryRunner的查询方法时, 如果我们要求要返回一个Java Bean的对象, 除了必须要提供一个空参构造器之外, 还要进行如下的考量
-
要清楚的知道自己的Java Bean所对应的表格的字段名和自己Java Bean的属性名是否一致, 如果不一致要使用别名来让我们的QueryRunner类中使用的ResultSetHandler的返回的Java Bean 的对象认识
-
假使我们的数据库表的字段名是user_name, user_password, 但是我们的Java Bean 中的是name 和 password 属性, 那么我们在使用QueryRunner 类进行查询时候就要用别名的方式来进行查询
-
select user_name as name, user_password as password from user_table where id = ? # 如果表中字段和我们的Java Bean不同的话, 我们可以使用这个方式.
-
- 可以参考我的另一篇博客 JDBC的通用增删改查操作(MySQL, 反射)]
5. 保存文件窗口的自动补全名称问题
-
在我们的Java中的JFileChooser在进行保存文件时, 需要自己输入文件名, 但是我们又需要这样一个功能, 因此, 我们可以使用下面这个通用的方法来获取我们的文件选择框的Text Field, 然后使用setText设置一下文件的名字.
/** * 获取我们的JTextField, 从我们的容器 {@code c}中 * @param c 容器 * @return 返回我们的TextField 框 */ public JTextField getTextField(Container c) { JTextField textField = null; for (int i = 0; i < c.getComponentCount(); i++) { Component cnt = c.getComponent(i); if (cnt instanceof JTextField) { return (JTextField) cnt; } if (cnt instanceof Container) { textField = getTextField((Container) cnt); if (textField != null) { return textField; } } } return textField; }
6. JTable的判空
- 只需要判断.getRowsCount()==0的结果就好了
7. 属性(Field)初始化问题
- 我们的属性中的数组初始化, 是在构造方法之前进行初始化, 如果我们的属性(Field)数组里面存在着构造方法的参数相关的元素, 很有可能会出现空指针的现象.
8. String 的MD5摘要算法
-
MD5摘要算法一般用在加密方面. MD5的摘要是一个32位的十六进制数组成的字符串. 可以作为密码的一种存储方式, 当我们在进行密码验证的时候, 可以通过比对这个MD5的摘要信息进行判定是否密码正确.
-
代码如下
import java.security.MessageDigest; /** * MD5的工具类, 将字符串转换为MD5摘要 * * @author Master_Joe qiaoguangtong@aliyun.com * */ public class MD5Utils { /** * 因为数据库中我们的存储数据是没有大写小写的, 因此可以使用大写, 也可以使用小写 */ private final static String[] hexArray = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; /*** * 对指定的字符串进行MD5加密 */ public static String encrypByMD5(String originString) { try { // 创建具有MD5算法的信息摘要 MessageDigest md = MessageDigest.getInstance("MD5"); // 使用指定的字节数组对摘要进行最后更新,然后完成摘要计算 byte[] bytes = md.digest(originString.getBytes()); // 将得到的字节数组变成字符串返回 String s = byteArrayToHex(bytes); return s.toUpperCase(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 将字节数组转换成十六进制,并以字符串的形式返回 128位是指二进制位。二进制太长,所以一般都改写成16进制, * 每一位16进制数可以代替4位二进制数,所以128位二进制数写成16进制就变成了128/4=32位。 */ private static String byteArrayToHex(byte[] b) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < b.length; i++) { sb.append(byteToHex(b[i])); } return sb.toString(); } /** * 将一个字节转换成十六进制,并以字符串的形式返回 */ public static String byteToHex(byte b) { int n = b; if (n < 0) n = n + 256; int d1 = n / 16; int d2 = n % 16; return hexArray[d1] + hexArray[d2]; } }
9. 邮箱的正则表达式
-
在输入注册信息时, 我们经常会有邮箱的输入, 但是如果不加限制的话, 用户可能会随便输入错误的邮箱, 因此, 邮箱的验证尤为重要, 在Java中我们可以使用一个叫做正则表达式的东西来进行邮箱格式的判断问题
-
代码如下
// 验证邮箱格式是否正确 // mailRegex是整体邮箱正则表达式,mailName是@前面的名称部分,mailDomain是后面的域名部分 String mailName = "^[0-9a-z]+\\w*"; // ^表明一行以什么开头;^[0-9a-z]表明要以数字或小写字母开头;\\w*表明匹配任意个大写小写字母或数字或下划线 String mailDomain = "([0-9a-z]+\\.)+[0-9a-z]+$"; // ***.***.***格式的域名,其中*为小写字母或数字;第一个括号代表有至少一个***.匹配单元,而[0-9a-z]$表明以小写字母或数字结尾 String mailRegex = mailName + "@" + mailDomain; // 邮箱正则表达式 ^[0-9a-z]+\w*@([0-9a-z]+\.)+[0-9a-z]+$ Pattern pattern = Pattern.compile(mailRegex); Matcher matcher = pattern.matcher(emailField.getText()); if (matcher.matches() || "".equals(emailField.getText())) { String email = emailField.getText(); }
10. JPopupMenu的元素问题
- 当我们在使用这个JPopupMenu组件的时候, 如果我们要使用数组来进行内容的填充的话, 那么我们在使用, setSelectedItem(Object object) 这个方法的时候, 我们不能将数组之外的元素设置在我们的选择框中.
11. Git&GitHub&Gitee
-
如果在使用Gitee或者GitHub托管的时候, 如果是先在网站上新建一个仓库, 然后再进行托管的话, 有可能推送失败.
-
我们需要在本地的Git命令窗口里面使用
git pull --rebase
这个命令会使我们远程库, 和本地库之间进行一个融合, 只是一个线性融合, 主要是因为我们Gitee.com网站创建的时候会出现一个ReadMe.en.md的文件, 这个文件需要与我们本地库的文件进行融合.
12. 总结
-
通过这个Swing简单项目, 我的解决问题能力提升了, 代码耐心也有了提高, 对于Git&GitHub&Gitee的使用更加的熟练了.
-
如果有错误, 欢迎评论区留言, 或者邮件联系我
qiaoguangtong@aliyun.com