咱是初哥,贴段自己的学习笔记,方便以后查看。
package com.icss.demo2;
import java.awt.EventQueue;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Properties;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <strong>用于小测试的一个类,大杂烩,不放辣椒的,我不喜欢辣椒。</strong>
* <p>
* 测试的内容有:<br/>
* 1、位运算符&在整数奇偶的判断上的应用<br/>
* 2、位运算<<和>><br/>
* 3、Scanner就用于控制台读取字符串<br/>
* 4、大数值BingDecimal对浮点数精度的处理<br/>
* 5、数组的拷贝与引用及其与基本类型数据的区别<br/>
* 6、打印当前系统的属性<br/>
* 7、类对象的浅克隆和深克隆<br/>
* 8、程序的配置<br/>
* 9、正则表达式的使用<br/>
* 10、打印字符数组时需要注意的一些问题<br/>
* </p>
*
* @author bing
* @version 2011-01-08
*
*/
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException{
Test1 test = new Test1();
///测试位运算符&在整数奇偶的判断上的应用//
/*int[] num = new int[10];
for(int i=0;i<num.length;i++){
num[i] = i-5;
}
for(int i : num){
System.out.println(i + " : " + test.isOdd(i));
}*/
///测试位运算<<和>>
输出,最后一个结果为负数是由于整数溢出 536870908 1073741816 2147483632 -32
/*int i;
int num = 0xFFFFFFE;
for (i = 0; i < 4; i++) {
num = num << 1;
System.out.println(num);
}*/
测试Scanner就用于控制台读取字符串/
// test.testScanner();
/*for(int i=0;i<3;i++){
test.testScanner();
}*/
///测试大数值BingDecimal对浮点数精度的处理
// test.testBigDecimal();
///测试数组的拷贝与引用及其与基本类型数据的区别/
// test.testArraysCopy();
//打印当前系统的属性
// test.printProperties();
/测试类对象的浅克隆和深克隆
// test.testFleetDeepClone();
程序的配置//
// test.testProgramConfig();
///正则表达式/
// test.testRegex();
///打印字符数组时需要注意的一些问题//
test.testCharArrayPrint();
}
/**
* 判断一个数(正或负整数)是否为奇数
* [2011-01-08 14:33]
* @param num
* @return
*/
public boolean isOdd(int num){
return (num & 1) == 1;
}
/**
* 使用Scanner读取字符串
*/
public void testScanner(){
Scanner scan = new Scanner(System.in);
System.out.print("Input a String:");
String str = scan.nextLine();
System.out.println("The String you input is \"" + str + "\".");
// 循环读取时关闭会抛出java.util.NoSuchElementException: No line found
// 异常,无论是不是在每次循环中重新new一个Scanner对象。
// 相关的描述见http://lifeising.javaeye.com/blog/633505
// scan.close();
}
/**
* 测试大数值BigDecimal
* 先看测试结果。
* java中的简单浮点数类型float和double不能进行数值精度的计算。使用float或double类型直接计算有时会出现精度丢失的问题,
* 而大数值BigDecimal类提供无限大小的数值计算,但是BigDecimal不重载+、*等的运算符,需要调用其提供的方法。
* 有人提出这样一个原则:float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal。
* 没做过实际的项目不发表意见,但是从这个测试中可以看出精度丢失带来的问题,特别是在金融业方面,这个数值计算带来的精度
* 的丢失最好是不要存在,否则.....
* 这就不说了,我又不开银行,哪天被别人利用bug刷了点钱或是抗了别人的钱,老板被人伏击,也不干我事...
* 不过要是我写出这种代码就不好了,咱做事都是兜着良心的...
* [2011-01-08 14:33]
*/
public void testBigDecimal(){
float f1 = 0.05f;
float f2 = 0.01f;
double d1 = 0.05;
double d2 = 0.01;
System.out.println(f1+f2);
// 由于BigDecimal的构造方法和静态方法valueOf中都没有处理float类型参数的,所以需要将float类型转换为String类型再构造BigDecimal
System.out.println((new BigDecimal(String.valueOf(f1))).add((new BigDecimal(String.valueOf(f2))))); // 可使用构造函数,也可以使用静态方法valueOf(Double d)
System.out.println(d1+d2);
System.out.println(BigDecimal.valueOf(d1).add(BigDecimal.valueOf(d2)));
}
/**
* 测试数组的拷贝与引用及其与基本类型数据的区别,测试int或String时把相应的变量增删注释即可。
* 拷贝与引用的区别,简单来说,如果A拷贝了B,则A不会因为B的改变而改变,如果A引用了B,则A会随着B的改变而改变,相当于是
* 一个物体的两个别名。
* 从测试中可以看出用一个数组直接通过“=”运算符赋值,是把两个数组变量指向同一块内存,相当于类的引用。拷贝一个数组到
* 另一个数组可以用void java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
* 或者T[] java.util.Arrays.copyOf(T[] original, int newLength),Arrays.copyOf方法常用于重建不同长度的数组。
* 而基本数据类型用直接通过“=”运算符赋值,是拷贝一个数据到另一个数据中。
*
* ps:数组的拷贝与引用类似于类对象的拷贝与引用,只是拷贝的方法有所不同,类对象的拷贝也叫克隆,使用clone方法实现,并且
* 需要该类实现Cloneable接口。不同的是,对象的克隆是对单个对象进行操作,数组的拷贝是对一组数据(包括对象)的拷贝。
* [2011-01-08 14:33]
*/
public void testArraysCopy(){
/测试数组的拷贝
// int[] array = new int[10];
// int[] copyArray = new int[10];
String[] array = new String[10];
String[] copyArray = new String[10];
for(int i=0;i<array.length;i++){
array[i] = i + "";
}
// copyArray = array; // copyArray引用array。copyArray与array指向同一块内存
// System.arraycopy(array, 0, copyArray, 0, array.length);// 将array拷贝到copyArray中
copyArray = Arrays.copyOf(array, Math.min(array.length, copyArray.length));// 将array拷贝到copyArray中
System.out.print("原array:");
// for(int i : array){
for(String i : array){
System.out.print(i + " ");
}
System.out.print("\n原copyArray:");
// for(int i : copyArray){
for(String i : copyArray){
System.out.print(i + " ");
}
// array[5] = 19; // 修改array值
array[5] = 19 + "";// 修改array值
System.out.print("\n新array:");
// for(int i : array){
for(String i : array){
System.out.print(i + " ");
}
System.out.print("\n新copyArray:");
// for(int i : copyArray){
for(String i : copyArray){
System.out.print(i + " ");
}
///测试基本数据的拷贝
// int a = 5;
// int b = a;
String a = 5 + "";
String b = a;
System.out.println("\na = " + a + "\tb = " + b);
// a = 6;
a = 6 + "";// 修改a值
System.out.println("a = " + a + "\tb = " + b);
//测试自定义类(用户类)数组的拷贝与引用/
Poker[] ps1 = new Poker[5];
Poker[] ps2 = new Poker[5];
for(int i=0;i<ps1.length;i++){
ps1[i] = new Poker("黑桃",(i%13)+1);
}
// ps2 = ps1; // 对象数组的引用,ps1和ps25指向同一块内存,是这块内存的两个别名
System.arraycopy(ps1, 0, ps2, 0, Math.min(ps1.length,ps2.length)); // 对象数组的拷贝
System.out.print("ps1原牌:");
for(Poker p : ps1){
System.out.print(p.toString());
}
System.out.print("\nps2原牌:");
for(Poker p : ps2){
System.out.print(p.toString());
}
// 修改ps1牌的花色
for(int i=0;i<ps1.length;i++){
ps1[i] = new Poker("梅花",(i%13)+1);
}
System.out.print("\nps1新牌:");
for(Poker p : ps1){
System.out.print(p.toString());
}
System.out.print("\nps2新牌:");
for(Poker p : ps2){
System.out.print(p.toString());
}
}
/**
* 打印当前系统的属性
*/
public void printProperties(){
Properties ps = System.getProperties();
System.out.println("当前系统的属性(共" + ps.size() + "个属性):");
for(Object key: ps.keySet()){
String strKey = (String)key;
System.out.println(strKey + " :\n " + ps.getProperty(strKey));
}
}
/**
* 测试对象的浅拷贝与深拷贝,即对象的浅克隆与深克隆。测试浅克隆或深克隆时把相应的测试语句增删注释即可。
* 由测试得知,浅克隆与深克隆的区别在于,浅克隆不会克隆类对象中包含的子类的对象属性,而深克隆则会。默认的克隆,即使用
* 超类(Object)的克隆方法super.clone()进行克隆,是浅克隆,所以要实现深克隆,则必须覆盖父类的克隆方法(clone)。
*/
public void testFleetDeepClone() throws CloneNotSupportedException{
ChildForTestClone child = new ChildForTestClone("child","I'm a child!");
ParentForTestClone parent1 = new ParentForTestClone("parent1","I'm parent1!",child);
ParentForTestClone parent2 = parent1.fleetClone(); // 浅克隆测试
// ParentForTestClone parent2 = parent1.deepClone(); // 深克隆测试
System.out.println("克隆:\n" + parent1.toString() + " " + parent1.getChild().toString()
+ "\n" + parent2.toString() + " " + parent2.getChild().toString() );
parent1.setName("parent1NewName");
System.out.println("修改parent1的属性之后:\n" + parent1.toString() + " " + parent1.getChild().toString()
+ "\n" + parent2.toString() + " " + parent2.getChild().toString() );
parent1.getChild().setName("childNewName");
System.out.println("修改parent1里的child(子对象)的属性之后:\n" + parent1.toString() + " " + parent1.getChild().toString()
+ "\n" + parent2.toString() + " " + parent2.getChild().toString() );
}
/**
* 测试程序的配置
*/
public void testProgramConfig(){
// 测试属性映射,利用属性文件(.properties)保存程序的配置
// EventQueue.invokeLater(new Runnable()
// {
// public void run()
// {
// PropertiesFrame frame = new PropertiesFrame();
// frame.setVisible(true);
// }
// });
// 测试Preferences API,利用操作系统提供的存储配置文件的中心知识库保存程序的配置
EventQueue.invokeLater(new Runnable()
{
public void run()
{
PreferencesFrame frame = new PreferencesFrame();
frame.setVisible(true);
}
});
/* System.out.println(new File("").getAbsolutePath());
System.out.println(System.getProperty("user.dir"));
System.out.println(Test1.class.getResource(""));
System.out.println(Test1.class.getResource("/"));*/
}
/**
* 正则表达式的使用
*/
public void testRegex(){
// 验证电子邮件地址
String regex1 = "\\w+(@|\\W)\\w+\\.((com(\\.cn)?)|(net))";
String str1 = "fhief#awyy_fd0fdfqe.com.cn";
System.out.println(Pattern.matches(regex1, str1));
// 验证24小时制时间格式
String regex2 = "(([01][0-9])|(2[0-3])):[0-5][0-9]:[0-5][0-9]";
String str2 = "23:00:00";
System.out.println(Pattern.matches(regex2, str2));
// 验证一句话中的haha子串
String regex3 = ".*:\".*(ha){2}.*\"\\W*";
String str3 = "cheatcode is:\"My father is LiGang,haha\"! ";
System.out.println(Pattern.matches(regex3, str3));
// 多次匹配(匹配的结果不尽人意)
/* 注:Pattrern.matches(String regex,String str)和Matcher的find(int start)方法匹配的时候是
* 如果后面有匹配的子字符串则返回true,如quaqm,这显然不是想要的结果,所有的努力都是要出现qu时就返回false。
* 而他们的这种匹配是匹配了整个字符串,如quaqm则匹配得到了两个结果false和true,然后用“或”联系则最后的结果是true。
* 换句话说,只要是有一个true,结果就是true,而我所需要的是只要有一个false就返回false。丫的不给力啊!!
* 丫的不给力,解决的方法只有把Matcher的find(int start)方法干掉,重写,用自己的规则实现自己的想法。
* 或者直接用String的子串操作来实现,直接查找“qu”,不过这种工作真的很无聊,把正则的匹配写成那样,也太那个了点。
*/
String regex4 = ".*q[^u].*";
String str4 = "zaqqquaqm";
// System.out.println(Pattern.matches(regex4, str4));
Pattern pa = Pattern.compile(regex4);
Matcher mat = pa.matcher(str4);
int index = 0; // 记录验证开始位
boolean flag; // 记录验证结果
while(true){
// System.out.println("mat.find(index) = " + mat.find(index)); // 输出匹配的调试信息,调试用
if(mat.find(index)){ // 从字符串的index位开始匹配。问题:如果后面有匹配的子字符串则返回true,如quadfdqm
index = str4.indexOf('q',index) + 1; // 下标后移1位,为下一次匹配做准备
flag = true;
// System.out.println("sub of str4 = " + str4.substring(index)); // 输出下一次匹配的调试信息,调试用
// System.out.println("flag = " + flag);
// System.out.println("index = " + index);
if(str4.indexOf('q', index) == -1) // 如果后面的子串中没有'q'则不再匹配
break;
continue;
}
flag = false;
break;
}
System.out.println(flag);
// 起始符与终止符
String regex5 = "^My$";
// String regex5 = "^$";
// String regex5 = "^";
String str5 = "Mfdfy";
System.out.println(Pattern.matches(regex5, str5));
}
/**
* 测试,打印字符数组时需要注意的一点,也就是数组与基本类型的不同。
* 数组对象是数组的一个引用,引用存放在内存的栈中,而实际数据(数组内容)存放在内存的堆中。
* 使用print((char[])+"")相当于调用print((new Char[]).toString+String),跟进查看源代码可知,最后调用的是print(String)方法,
* 输出的是引用的内存地址,而不是数组的内容。
* 而使用print(char[])输出的则是数组的内容,跟进查看源代码可知,归后调用的是write(int c)方法。
*
* 本测试中,cs是引用,c是基本数据类型,打印引用是会调用类的toString方法的,而打印基本数据类弄就不会如此做,""+基本数据类型,
* 会调用String.valueOf(基本数据类型),将数据转换为字符串。要知道,基本数据类型不是对象,是不会有toString方法的,甚至是没有方法的。
*
* [2011-01-22 14:46]
*/
public void testCharArrayPrint(){
String str = "abcdef";
char[] cs = str.toCharArray(); // 注意,数组对象(cs)是数组的一个引用
System.out.println(cs); // 调用println(String)
System.out.println("" + cs.toString());// 调用println(char[]) 将字符数组转换成字符串输出时会输出字符数组的类型+哈希码
char c = 'a';
System.out.println(c);
System.out.println(""+c);
}
}
ChildForTestClone 源代码
package com.icss.demo2;
public class ChildForTestClone implements Cloneable{
private String name;
private String info;
public ChildForTestClone(){
}
public ChildForTestClone(String name,String info){
this.name = name;
this.info = info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
/**
* @retruns 子对象的名(子对象的描述)
*/
public String toString() {
return this.name + "(" + this.info + ")";
}
/**
* 默认克隆(浅克隆)
* @return
* @throws CloneNotSupportedException
*/
public ChildForTestClone clone() throws CloneNotSupportedException{
return (ChildForTestClone)super.clone();
}
}
ParentForTestClone 源代码
package com.icss.demo2;
public class ParentForTestClone implements Cloneable{
private String name;
private String info;
private ChildForTestClone child;
public ParentForTestClone(){
}
public ParentForTestClone(String name,String info){
this.name = name;
this.info = info;
}
public ParentForTestClone(String name,String info,ChildForTestClone child){
this.name = name;
this.info = info;
this.child = child;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public ChildForTestClone getChild() {
return child;
}
public void setChild(ChildForTestClone child) {
this.child = child;
}
/**
* @retrun 父对象的名(父对象的描述)[父对象中包含的子对象的名]
*/
public String toString() {
return this.name + "(" + this.info + ")[" + this.child.getName() + "]";
}
/**
* 深克隆(深拷贝)
* @return 返回一个克隆对象,深克隆克隆类中包含的子类属性
*/
protected ParentForTestClone deepClone() throws CloneNotSupportedException {
ParentForTestClone cloneObject = (ParentForTestClone)super.clone(); // 克隆对象
cloneObject.setName(this.name);
cloneObject.setInfo(this.info);
cloneObject.setChild(this.child.clone());// 克隆子类属性
return cloneObject;
}
/**
* 浅克隆(浅拷贝),默认的克隆时浅克隆,浅克隆不会克隆类中包含的子类属性,而是做引用处理
* @return
* @throws CloneNotSupportedException
*/
protected ParentForTestClone fleetClone() throws CloneNotSupportedException {
return (ParentForTestClone)super.clone(); // 默认的拷贝
}
}