情不知所起,一往而深。恨不知所踪,一笑而泯。

Java学习篇之---Maven打包资源配置

Maven打包资源配置

在pom.xml文件中配置如下:

    <configuration>  
                                <outputDirectory>${staging.windows.dir}</outputDirectory>  
                                <resources>  
                                    <resource>  
                                        <directory>src/main/resources</directory>  
                                        <includes>  
                                            <include>resourceName.dll</include>  
                                        </includes>  
                                    </resource>  
                                    <resource>  
                                        <directory>.</directory>  
                                        <includes>  
                                            <include>release_notes.txt</include>  
                                            <include>configuration.md</include>  
                                            <include>COPYING</include>  
                                            <include>authors.txt</include>  
                                        </includes>  
                                    </resource>  
                                </resources>  
    </configuration>  

将需要打包的文件配置在include标签中,需要打包的文件的所在目录配置在directory中。

然后配置projectName\src\main\izpack\windows\目录中的Install文件:

    <packs>  
      <pack name="MultiBit" required="yes">  
        <description>MultiBit install files.</description>  
        <file src="configuration.md" targetdir="$INSTALL_PATH"/>  
        <file src="release_notes.txt" targetdir="$INSTALL_PATH"/>  
        <file src="COPYING" targetdir="$INSTALL_PATH"/>  
        <file src="authors.txt" targetdir="$INSTALL_PATH"/>  
        <file src="<span style="font-family: Arial, Helvetica, sans-serif;">resourceName.dll</span>" targetdir="$INSTALL_PATH"/>  
      </pack>  
    </packs>  


然后配置好后生成的安装程序就会将所需打包的文件包含在内。

点击安装程序进行安装程序的时候,就会将资源重新copy进安装目录

Java学习篇之---修饰符final详解

修饰符final详解

最近又翻看了一遍Java的基础知识,发现当初自己关于修饰符final的理解就曾经迷茫过,为了帮助Java初学者更好度过迷茫期,特此献上此文(此文将重点讲解final修饰的变量,至于final修饰的类和方法,由于比较简单,就不再下面列出了)。

一、概述:

    final关键字可用于修饰类、变量和方法。final修饰变量时,表示该变量一旦获得了初始值就不可被改变(可以赋初值,但是不可以被改变),final既可以修饰成员变量(包括类变量和实例变量),也可以修饰局部变量、形参。

二、final成员变量:

1) 类变量:

final修饰类变量,要么在定义该类变量时指定初始值;要么在静态初始化块中指定初始值。

    /*正确代码演示*/  
    public class FinalClassTest{  
        final static int a=210;//在定义该类变量时指定初始值;  
        final static int b;  
      
        static{  
            b=211;//在静态初始化块中指定初始值;  
        }  
    }  
      
    /*错误代码演示*/  
    public class FinalClassErrorTest{  
        final static int aa=110;  
        final static int bb;  
        //系统不会为final成员变量(类变量和实例变量)进行隐形初始化;而此类变量既没有在定义时指定初始值,又没有在静态初始化块中指定初始值,所以非法。  
      
        final static int cc;  
      
        static{  
            aa=111;//类变量已经定义了初始值,不能再次赋值,因此此语句非法;  
        }  
      
        public void finalClassChange(){  
            bb=112;//在普通方法中为类变量赋值,因此此语句非法;  
        }  
    }  


2) 实例变量:

final修饰实例变量,要么在定义该实例变量时指定初始值;要么在普通初始化块中指定初始值;要么在构造器中指定初始值。


    /*正确代码演示*/  
    public class FinalInstanceTest{  
        final int c=310;//在定义该实例变量时指定初始值;  
        final int d;  
        final int e;  
      
        {  
            d=311;//在普通初始化块中指定初始值;  
        }  
          
        public FinalInstanceTest(){  
            e=312;//在构造器中指定初始值;  
        }  
    }  
      
    /*错误代码演示*/  
    public class FinalInstanceErrorTest{  
        final int cc=410;  
        final int dd;  
    //系统不会为final成员变量(类变量和实例变量)进行隐形初始化;而此实例变量既没有在定义时指定初始值,又没有在普通初始化块中指定初始值,又没有在构造器中赋值,所以非法。  
      
        final int ee;  
      
        {  
            cc=411;//实例变量已经定义了初始值,不能再次赋值,因此此语句非法;  
        }  
      
        public void finalInstanceChange(){  
            dd=412;//在普通方法中为实例变量赋值,因此此语句非法;  
        }  
      
        public FinalInstanceErrorTest(){  
      
        }  
    }  

三、final局部变量:

系统不会对局部变量进行隐形初始化,需要程序员显性初始化。

    public class FinalLocalTest{  
      
        public void invokTest(final int f){  
      
            f=510;//对final修饰的形参变量赋值,非法;  
      
            //该方法被调用时,由系统根据传入的参数来对形参完成初始化;  
      
        }  
      
        public void mainTest(){  
      
            final int g=511;//定义final变量时指定初始值,合法;  
      
            final int h;  
      
            h=512;//第一次赋初始值,合法;  
      
        }  
    }  


四、final修饰基本类型变量和引用类型变量的区别:

final修饰基本类型变量时,不能对基本类型变量重新赋值;对于引用类型而言,它保存的只是一个引用,final只保证这个引用类型变量所引用的地址不变,即一直引用同一个对象,但是这个对象的成员可以改变;

    class Student{  
        privte int age;  
        public Student(int age){  
      
            this.age=age;  
      
        }  
        //此处省略age的setter和getter方法;  
    }  
      
    public class FinalReferenceTest{  
      
        public static void main(String[]  args){  
            //final修饰数组变量,iArray是一个引用变量;  
            final int[] iArray={5,6,7,8};  
            Arrays.sort(iArray);//对数组元素进行排序,合法;  
            iArray[3]=9;//对数组元素赋值,合法;  
            iArray=null;//对iArray重新赋值,非法;  
            final Student st=new Student(21);  
            st.setAge(23);//改变Student对象的age实例变量,合法;  
            st=null;//对st重新赋值,非法;  
        }  
    }  


五、可执行"宏替换"的final变量:

对于一个final变量而言,不管是类变量、实例变量还是局部变量,只要该变量满足以下三条,则final变量就不再是一个变量,而是相当于是一个直接值:

1、使用final修饰符修饰;

2、在定义该final变量时指定了初始值;

3、该初始值可以在编译时就确定下来。


    public class MacroFinalTest{  
        public static void main(String[] args){  
            final String domainName="pplns.com";  
            final String domain="pplns"+".com";  
            System.out.println(domainName==domain);//返回值为true;  
      
            final String domainPrefix="pplns";  
            final String domainSuffix=".com";  
            final String myDomain=domainPrefix+domainSuffix;  
            System.out.println(domainName==myDomain);//返回值为true;  
        }  
    }  


    public class MacroTest{   
        public static void main(String[] args){   
            String domainName="pplns.com";   
            String domain="pplns"+".com";   
            System.out.println(domainName==domain);//返回值为true;  
            String domainPrefix="pplns";   
            String domainSuffix=".com";   
            String myDomain=domainPrefix+domainSuffix;   
            System.out.println(domainName==myDomain);//返回值为false;  
        }  
    }   


以上特意用final修饰的变量和无final修饰的变量进行对比,从而发现不同之处。

Java通过一个常量池来管理曾经用过的字符串常量,例如执行String domain="pplns.com";语句之后,常量池中就缓存了一个字符串“pplns.com”;如果程序再执行String domainName="pplns.com";,系统将会让domainName直接指向常量池中“pplns”字符串,因此domain==domainName将返回true;但是在上例MacroTest类中,myDomain是由两个变量拼接而成,而变量在编译期间是不会确定下来,只有在运行期间才会确定下来,所以domainName==myDomain返回的是false;而在上例MacroFinalTest类中,domainPrefix和domainSuffix是由final修饰的变量,所以这两个变量在编译期间就会当作“宏变量”,即常量来处理,所以myDomain在编译期间实际是由"pplns"和".com"拼接而成,所以domainName==myDomain返回的是true。

Java学习篇之---Collection接口

Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。JavaSDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。

所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。

如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:


    Iterator it = collection.iterator(); // 获得一个迭代子    
    while(it.hasNext())     
    {    
    Object obj = it.next(); // 得到下一个元素    
    }  

由Collection接口派生的两个接口是List和Set。


    Collection    
    ├List    
    │├LinkedList    
    │├ArrayList    
    │└Vector    
    │ └Stack    
    └Set   

易混淆:

1、java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
2、java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。


        import java.util.ArrayList;    
        import java.util.Collections;    
        import java.util.List;    
            
        public class TestCollections {    
                
            public static void main(String args[]) {    
                       //注意List是实现Collection接口的    
                List list = new ArrayList();    
                int array[] = { 6, 8, 23, 1, 7 };    
                for (int i = 0; i < array.length; i++) {    
                    list.add(array[i]);    
                }    
                Collections.sort(list);    
                for (int i = 0; i < array.length; i++) {    
                    System.out.println(list.get(i));    
                }     
            }    
        }    
    结果:  
    1  
    6  
    7  
    8  
    23

Java学习篇之---LinkedList

LinkedList

Java.util.LinkedList是双向链表。

LinkedList的两个remove方法,remove(Object)和remove(int)的时间复杂度都是O(n),在链表元素很多 并且没有索引可用的情况下,LinkedList也并不适合做随机增删元素。在对性能特别敏感的场景下,还是需要自己实现专用的双向链表结构,真正实现 O(1)级别的随机增删。更进一步,jdk5引入的ConcurrentLinkedQueue是一个非阻塞的线程安全的双向队列实现。

理论上说,双向链表的删除的时间复杂度是O(1),你只需要将要删除的节点的前节点和后节点相连,然后将要删除的节点的前节点和后节点置为null即可:


    //伪代码  
      node.prev.next=node.next;  
      node.next.prev=node.prev;  
      node.prev=node.next=null;  

注意:

ArrayList和LinkedList的区 别之在什么场景下用:

大家都会说LinkedList随机增删多的场景比较合适,而ArrayList的随机访问多的场景比较合适。

Java学习篇之---byte与十六进制字符串之间互转

byte与十六进制字符串之间互转

byte,字节类型,占用8bit空间,可用8位2进制数表示;十六进制,每位占有4bit空间,可用4位2进制数表示。
我们可以把每个byte类型转换成两个相应的16进制字符,即把byte的高4位和低4位分别转换成相应的16进制字符H和L,并组合起来得到byte转换到16进制字符串的结果。
即byte用十六进制表示只占2位。
同理,相反的转换也是将两个16进制字符转换成一个byte。
根据以上原理,我们就可以将byte[] 数组转换为16进制字符串了,当然也可以将16进制字符串转换为byte[]数组了。


     * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。     
     * @param src byte[] data     
     * @return hex string     
     */        
    public static String bytesToHexString(byte[] src){     
        StringBuilder stringBuilder = new StringBuilder("");     
        if (src == null || src.length <= 0) {     
            return null;     
        }     
        for (int i = 0; i < src.length; i++) {     
            int v = src[i] & 0xFF;     
            String hv = Integer.toHexString(v);     
            if (hv.length() < 2) {     
                stringBuilder.append(0);     
            }     
            stringBuilder.append(hv);     
        }     
        return stringBuilder.toString();     
    }  

    /**   
     * Convert hex string to byte[]   
     * @param hexString the hex string   
     * @return byte[]   
     */    
    public static byte[] hexStringToBytes(String hexString) {     
        if (hexString == null || hexString.equals("")) {     
            return null;     
        }     
        hexString = hexString.toUpperCase();     
        int length = hexString.length() / 2;     
        char[] hexChars = hexString.toCharArray();     
        byte[] d = new byte[length];     
        for (int i = 0; i < length; i++) {     
            int pos = i * 2;     
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));     
        }     
        return d;     
    }    

    /**   
     * Convert char to byte   
     * @param c char   
     * @return byte   
     */    
     private byte charToByte(char c) {     
        return (byte) "0123456789ABCDEF".indexOf(c);     
    }  


    //将指定byte数组以16进制的形式打印到控制台     
    public static void printHexString( byte[] b) {       
       for (int i = 0; i < b.length; i++) {      
         String hex = Integer.toHexString(b[i] & 0xFF);      
         if (hex.length() == 1) {      
           hex = '0' + hex;      
         }      
         System.out.print(hex.toUpperCase() );      
       }      
        
    }  


java中byte转换int时为何与0xff进行与运算
在剖析该问题前请看如下代码

    public static String bytes2HexString(byte[] b) {     
      String ret = "";     
      for (int i = 0; i < b.length; i++) {     
       String hex = Integer.toHexString(b[ i ] & 0xFF);     
       if (hex.length() == 1) {     
        hex = '0' + hex;     
       }     
       ret += hex.toUpperCase();     
      }     
      return ret;     
    }  


上面是将byte[]转化十六进制的字符串,注意这里b[ i ] & 0xFF将一个byte和 0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出
b[ i ] & 0xFF运算后得出的仍然是个int,那么为何要和 0xFF进行与运算呢?直接 Integer.toHexString(b[ i ]);,将byte强转为int不行吗?答案是不行的。

其原因在于:
1.byte的大小为8bits而int的大小为32bits
2.java的二进制采用的是补码形式

在这里先温习下计算机基础理论:
byte是一个字节保存的,有8个位,即8个0、1。
8位的第一个位是符号位,
也就是说0000 0001代表的是数字1
1000 0000代表的就是-1
所以正数最大位0111 1111,也就是数字127
负数最大为1111 1111,也就是数字-128

上面说的是二进制原码,但是在java中采用的是补码的形式,下面介绍下什么是补码:
1、反码:
        一个数如果是正,则它的反码与原码相同;
        一个数如果是负,则符号位为1,其余各位是对原码取反;
2、补码:利用溢出,我们可以将减法变成加法
       对于十进制数,从9得到5可用减法:
       9-4=5    因为4+6=10,我们可以将6作为4的补数
       改写为加法:
       9+6=15(去掉高位1,也就是减10)得到5.

       对于十六进制数,从c到5可用减法:
       c-7=5    因为7+9=16 将9作为7的补数
       改写为加法:
       c+9=15(去掉高位1,也就是减16)得到5.

    在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为(100000000),进位1被丢弃。

    ⑴一个数为正,则它的原码、反码、补码相同
    ⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1
   
- 1的原码为                10000001
- 1的反码为                11111110
                                                   + 1
- 1的补码为                11111111

0的原码为                 00000000
0的反码为                 11111111(正零和负零的反码相同)
                                          +1
0的补码为               100000000(舍掉打头的1,正零和负零的补码相同)

Integer.toHexString的参数是int,如果不进行&0xff,那么当一个byte会转换成int时,由于int是32位,而byte只有8位这时会进行补位,
例如补码11111111的十进制数为-1转换为int时变为11111111111111111111111111111111好多1啊,呵呵!即0xffffffff但是这个数是不对的,这种补位就会造成误差。
和0xff相与后,高24比特就会被清0了,结果就对了。

Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展,举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是我们想要的了。

而0xff默认是整形,所以,一个byte跟0xff相与会先将那个byte转化成整形运算,这样,结果中的高的24个比特就总会被清0,于是结果总是我们想要的。

 

Java学习篇之---Mysql中varchar类型总结

Mysql中varchar类型总结

今天新做一个项目,需要自己进行数据库设计,发现自己对varchar的用法还不是很熟悉,所以查阅资料总结若下:

1.varchar类型的变化

MySQL 数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255(根据不同版本数据库来定)。在 MySQL5.0以上的版本中,varchar数据类型的长度支持到了65535,也就是说可以存放65532个字节的数据,起始位和结束位占去了3个字 节,也就是说,在4.1或以下版本中需要使用固定的TEXT或BLOB格式存放的数据可以使用可变长的varchar来存放,这样就能有效的减少数据库文 件的大小。

MySQL 数据库的varchar类型在4.1以下的版本中,nvarchar(存储的是Unicode数据类型的字符)不管是一个字符还是一个汉字,都存为2个字节 ,一般用作中文或者其他语言输入,这样不容易乱码 ;varchar: 汉字是2个字节,其他字符存为1个字节 ,varchar适合输入英文和数字。

4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) ;5.0版本以上,varchar(20),指的是20字符,无论存放的是数字、字母还是UTF8汉字(每个汉字3字节),都可以存放20个,最大大小是65532字节 ;varchar(20)在Mysql4中最大也不过是20个字节,但是Mysql5根据编码不同,存储大小也不同,具体有以下规则:

a) 存储限制

varchar 字段是将实际内容单独存储在聚簇索引之外,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535。

b) 编码长度限制

字符类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766;

字符类型若为utf8,每个字符最多占3个字节,最大长度不能超过21845。

若定义的时候超过上述限制,则varchar字段会被强行转为text类型,并产生warning。

c) 行长度限制

导致实际应用中varchar长度限制的是一个行定义的长度。 MySQL要求一个行的定义长度不能超过65535。若定义的表长度超过这个值,则提示

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。
2.CHAR(M), VARCHAR(M)不同之处

CHAR(M)定义的列的长度为固定的,M取值可以为0~255之间,当保存CHAR值时,在它们的右边填充空格以达到指定的长度。当检索到CHAR值时,尾部的空格被删除掉。在存储或检索过程中不进行大小写转换。CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充。

VARCHAR(M)定义的列的长度为可变长字符串,M取值可以为0~65535之间,(VARCHAR的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是65,532字节)。VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节)。VARCHAR值保存时不进行填充。当值保存和检索时尾部的空格仍保留,符合标准SQL。varchar存储变长数据,但存储效率没有CHAR高。如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么"+1"呢?这一个字节用于保存实际使用了多大的长度。从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。

CHAR和VARCHAR最大的不同就是一个是固定长度,一个是可变长度。由于是可变长度,因此实际存储的时候是实际字符串再加上一个记录字符串长度的字节(如果超过255则需要两个字节)。如果分配给CHAR或VARCHAR列的值超过列的最大长度,则对值进行裁剪以使其适合。如果被裁掉的字符不是空格,则会产生一条警告。如果裁剪非空格字符,则会造成错误(而不是警告)并通过使用严格SQL模式禁用值的插入。
3. VARCHAR和TEXT、BlOB类型的区别

VARCHAR,BLOB和TEXT类型是变长类型,对于其存储需求取决于列值的实际长度(在前面的表格中用L表示),而不是取决于类型的最大可能尺寸。例如,一个VARCHAR(10)列能保存最大长度为10个字符的一个字符串,实际的存储需要是字符串的长度 ,加上1个字节以记录字符串的长度。对于字符串'abcd',L是4而存储要求是5个字节。

BLOB和TEXT类型需要1,2,3或4个字节来记录列值的长度,这取决于类型的最大可能长度。VARCHAR需要定义大小,有65535字节的最大限制;TEXT则不需要。如果你把一个超过列类型最大长度的值赋给一个BLOB或TEXT列,值被截断以适合它。

一个BLOB是一个能保存可变数量的数据的二进制的大对象。4个BLOB类型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB仅仅在他们能保存值的最大长度方面有所不同。

BLOB 可以储存图片,TEXT不行,TEXT只能储存纯文本文件。4个TEXT类型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT对应于4个BLOB类型,并且有同样的最大长度和存储需求。在BLOB和TEXT类型之间的唯一差别是对BLOB值的排序和比较以大小写敏感方式执行,而对TEXT值是大小写不敏感的。换句话说,一个TEXT是一个大小写不敏感的BLOB。
4.char,varchar,text区别

长度的区别,char范围是0~255,varchar最长是64k,但是注意这里的64k是整个row的长度,要考虑到其它的column,还有如果存在not null的时候也会占用一位,对不同的字符集,有效长度还不一样,比如utf8的,最多21845,还要除去别的column,但是varchar在一般情况下存储都够用了。如果遇到了大文本,考虑使用text,最大能到4G。

效率来说基本是char>varchar>text,但是如果使用的是Innodb引擎的话,推荐使用varchar代替char

char和varchar可以有默认值,text不能指定默认值

数据库选择合适的数据类型存储还是很有必要的,对性能有一定影响。这里在零碎记录两笔,对于int类型的,如果不需要存取负值,最好加上unsigned;对于经常出现在where语句中的字段,考虑加索引,整形的尤其适合加索引。
5.varchar(10)和varchar(100)的区别

一般初学会认为,二者占用的空间是一样的。比如说我存储5个char,二者都是实际占用了5个char了【勘误:varchar在实际存储的时候会多一个byte用来存放长度】。
但是深入一下,设计数据库的时候,二者一样吗?
答案是否定的【至少varchar类型需要在数据之前利用一个或者两个字节来存储数据的长度】【二者在内存中的操作方式也是不同的,下面的例子中有体现】。
如现在用户需要存储一个地址信息。根据评估,只要使用100个字符就可以了。但是有些数据库管理员会认为,反正Varchar数据类型是根据实际的需要来分配长度的。还不如给其大一点的呢。为此他们可能会为这个字段一次性分配200个字符的存储空间。这VARCHAR(100)与VARCHAR(200)真的相同吗?结果是否定的。虽然他们用来存储90个字符的数据,其存储空间相同。但是对于内存的消耗是不同的。对于VARCHAR数据类型来说,硬盘上的存储空间虽然都是根据实际字符长度来分配存储空间的,但是对于内存来说,则不是。其时使用固定大小的内存块来保存值。简单的说,就是使用字符类型中定义的长度,即200个字符空间。显然,这对于排序或者临时表(这些内容都需要通过内存来实现)作业会产生比较大的不利影响。解释可以参见这里。所以如果某些字段会涉及到文件排序或者基于磁盘的临时表时,分配VARCHAR数据类型时仍然不能够太过于慷慨。还是要评估实际需要的长度,然后选择一个最长的字段来设置字符长度。如果为了考虑冗余,可以留10%左右的字符长度。千万不能认为其为根据实际长度来分配存储空间,而随意的分配长度,或者说干脆使用最大的字符长度。

6.char的利弊

1)、从碎片角度进行考虑,使用CHAR字符型时,由于存储空间都是一次性分配的。为此某个字段的内容,其都是存储在一起的。单从这个角度来讲,其不存在碎片的困扰。而可变长度的字符数据类型,其存储的长度是可变的。当其更改前后数据长度不一致时,就不可避免的会出现碎片的问题。故使用可变长度的字符型数据时,数据库管理员要时不时的对碎片进行整理。如执行数据库导出导入作业,来消除碎片。
2)、考虑其长度的是否相近,如果某个字段其长度虽然比较长,但是其长度总是近似的,如一般在90个到100个字符之间,甚至是相同的长度。此时比较适合采用CHAR字符类型。比较典型的应用就是MD5哈希值。当利用MD5哈希值来存储用户密码时,就非常使用采用CHAR字符类型。因为其长度是相同的。另外,像用来存储用户的身份证号码等等,一般也建议使用CHAR类型的数据。
另外请大家考虑一个问题,CHAR(1)与VARCHAR(1)两这个定义,会有什么区别呢?虽然这两个都只能够用来保存单个的字符,但是VARCHAR要比CHAR多占用一个存储位置。这主要是因为使用VARCHAR数据类型时,会多用1个字节用来存储长度信息。这个管理上的开销char字符类型是没有的。

3)、二者在磁盘上存储占的空间是一样的。区别有二。第一、一个变长一个固定长度。第二、在内存中的操作方式,varchar也是按照最长的方式在内存中进行操作的。比如说要进行排序的时候,varcahr(100)是按照100这个长度来进行的。

4)、mysql的vachar字段的类型虽然最大长度是65535,但是并不是能存这么多数据,最大可以到65533(不允许非空字段的时候),当允许非空字段的时候只能到65532【在允许空的时候,varchar(65532) will be 2 bytes (length) + up to 65532 chars (latin1) + 1 null byte】

5)、请注意所有MySQL校对规则属于PADSPACE类。这说明在MySQL中的所有CHAR和VARCHAR值比较时不需要考虑任何尾部空格。请注意所有MySQL版本均如此,并且它不受SQL服务器模式的影响。如果在一个char或者varchar列上建立唯一索引之后,那么'a'和'a ',会引起duplicate-key error。

Java学习篇之--检测主机是否在线Ping

检测主机是否在线Ping

    最近想写个程序,检测一下远程主机是否在线,于是在网上找到了很多前辈的方法,现在总结一下,分享给大家,希望能够抛砖引玉:

    方法一:利用Java.net包中的类InetAddress中的getByAddress()方法:

    函数原型:  
    public static InetAddress getByAddress(byte[] addr) throws UnknownHostException  

    public boolean isReachable(int timeout) throws IOException  


    注释:Test whether that address is reachable.

    源码:  
    package com.ryze.ping.test;  
      
    import java.io.IOException;  
    import java.net.InetAddress;  
    import java.net.UnknownHostException;  
      
    public class PingTest {  
      
        public static void main(String[] args) throws UnknownHostException, IOException {  
            InetAddress inet;  
            inet = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });  
            System.out.println("Sending Ping Request to " + inet);  
            System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");  
      
            inet = InetAddress.getByAddress(new byte[] { (byte) 220, (byte) 181, 112, (byte)244 });  
            System.out.println("Sending Ping Request to " + inet);  
            System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");  
        }  
    }  


    运行结果:  
    Sending Ping Request to /127.0.0.1  
    Host is reachable  
    Sending Ping Request to /220.181.112.244  
    Host is NOT reachable  

    方法二:利用java.net包中的类InetAddress中的getByName()方法:

    函数原型:  
    public static InetAddress getByName(String host) throws UnknownHostException  

    源码:  
    package com.ryze.ping.test;  
      
    import java.io.IOException;  
    import java.net.InetAddress;  
    import java.net.UnknownHostException;  
      
    public class PingTest {  
      
        public static void main(String[] args) throws UnknownHostException, IOException {  
            String ipAddress = "127.0.0.1";  
            InetAddress inet = InetAddress.getByName(ipAddress);  
      
            System.out.println("Sending Ping Request to " + ipAddress);  
            System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");  
      
            ipAddress = "220.181.112.244";  
            inet = InetAddress.getByName(ipAddress);  
      
            System.out.println("Sending Ping Request to " + ipAddress);  
            System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");  
        }  
    }  

    运行结果:  
    Sending Ping Request to 127.0.0.1  
    Host is reachable  
    Sending Ping Request to 220.181.112.244  
    Host is NOT reachable  

    方法三:利用java.lang包中的类Runtime中的getRuntime()方法:

    函数原型:  
    public static Runtime getRuntime()  


    注释:returns the runtime object associated with the current Java application.


    函数原型:  
    public Process exec(String command)  throws IOException  


    注释:Executes the specified string command in a separate process.

    函数原型:  
    public abstract int waitFor() throws InterruptedException  


    注释:the exit value of the subprocess represented by this Process object. By convention, the value 0 indicates normal termination.

    源码:  
    package com.ryze.ping.test;  
      
    public class PingTest {  
      
        public static void main(String[] args) {  
                      
            boolean reachable = false;  
            Process process;  
            try {  
                String ipAddress = "127.0.0.1";  
                process = Runtime.getRuntime().exec("ping " + ipAddress);  
                int returnVal = process.waitFor();  
                reachable = returnVal == 0?true:false;  
                System.out.println("Sending Ping Request to " + ipAddress);  
                System.out.println(reachable ? "Host is reachable" : "Host is NOT reachable");  
                  
                ipAddress = "220.181.112.244";  
                process = Runtime.getRuntime().exec("ping " + ipAddress);  
                returnVal = process.waitFor();  
                reachable = returnVal == 0?true:false;  
                System.out.println("Sending Ping Request to " + ipAddress);  
                System.out.println(reachable ? "Host is reachable" : "Host is NOT reachable");  
            } catch (Exception ex) {  
                ex.printStackTrace();  
            }  
        }  
    }  

    运行结果:  
    Sending Ping Request to 127.0.0.1  
    Host is reachable  
    Sending Ping Request to 220.181.112.244  
    Host is reachable  


    小结:通过google搜索加上自己亲自实验,发现前两种方法只能ping通局域网内的Ip,对于外网的ip一般ping不通,第三种方法我的理解是相当于在本地DOS环境下进行ping,能ping通外网,但是每ping一次效率很低。

Java学习篇之--eclipse中JDK源码查看

eclipse中JDK源码查看

用eclipse工具开发项目时,时常按住Ctrl+鼠标左键点击一个类,返回的却是无法追踪类的源码的提示:

此时:

步骤一:在Java代码中按住Ctrl + 鼠标左键追逐某个Java内部类,出现如图所示:

步骤二:单击Change Attached Source,选择JDK安装所在的目录下src.zip,如下图所示:

步骤三:再次追踪某个Java类,将会追踪进Java源码内部。

希望以上信息对学习Java的童鞋们有一定帮助!

Java学习篇之---基本数据类型

基本数据类型

Java中一共有八种基本数据类型,可以分为四类:

第一类(整型)    :byte  short   int   long

第二类(浮点型):float   double

第三类(逻辑型):boolean

第四类(字符型):char

    名称          类型        占用内存数(单位:字节)  
    布尔型        boolean     1/8  
    字符型        char        2  
    单精度        float       4  
    双精度        double      8  
    字节型        byte        1  
    短整型        short       2  
    整数型        int         4  
    长整型        long        8  

注意:

1、Java中默认的整数类型是int类型,如果要定义为long类型,则要在数值后加l或L。

           默认的浮点类型是double类型,如果要定义为float类型,则要在数值后加f或F。

2、1Bytes(字节)=8bit(比特)
一般讲大小是用Bytes,大写的“B”,讲网络速率是用bit,注意是小写的“b”。
例:一个文件有8MBytes
例:我下载文件的速率是256KB/s,即2Mbit,这通常就是我们宽带上网的速率。

3、基本数据类型在栈里面直接分配内存,而引用数据则是通过堆里的对象来对栈中的内容进行引用。

Java学习篇之---环境变量和系统属性

环境变量和系统属性

一、前言:

    Java环境变量(getenv)与系统属性(getProperties)
    getenv是获取系统的环境变量,对于windows是将系统属性-->高级-->环境变量中设置的变量显示在此(对于linux是将通过export设置的变量显示在此)。
    getProperties是获取系统的相关属性,包括文件编码,操作系统名称,区域,用户名等,此属性一般由jvm自动获取,不能设置。     

    System.out.println(System.getenv());  
    erties().list(System.err);  

二、系统属性:
    System.out.println("Java的虚拟机实现名称:"+ System.getProperty("java.vm.name"));  
    System.out.println("Java的虚拟机实现供应商:"+ System.getProperty("java.vm.vendor"));  
    System.out.println("Java的虚拟机实现版本:"+ System.getProperty("java.vm.version"));  
    System.out.println("Java的虚拟机规范名称:"+ System.getProperty("java.vm.specification.name"));  
    System.out.println("Java的虚拟机规范供应商:"+ System.getProperty("java.vm.specification.vendor"));  
    System.out.println("Java 虚拟机规范版本:"+ System.getProperty("java.vm.specification.version"));  
    System.out.println("Java运行时环境版本:" + System.getProperty("java.version"));  
    System.out.println("Java运行时环境规范版本:" + System.getProperty("java.specification.version"));  
    System.out.println("Java运行时环境规范名称:" + System.getProperty("java.specification.name"));  
    System.out.println("Java 运行时环境供应商:" + System.getProperty("java.vendor"));  
    System.out.println("Java 供应商的URL:"+ System.getProperty("java.vendor.url"));  
    System.out.println("Java安装目录:" + System.getProperty("java.home"));  
    System.out.println("Java 类格式版本号:"+ System.getProperty("java.class.version"));  
    System.out.println("Java类路径:" + System.getProperty("java.class.path"));  
    System.out.println("默认的临时文件路径:" + System.getProperty("java.io.tmpdir"));  
    System.out.println("一个或多个扩展目录的路径:" + System.getProperty("java.ext.dirs"));  
    System.out.println("加载库时搜索的路径列表:" + System.getProperty("java.library.path"));  
    System.out.println("操作系统的名称:" + System.getProperty("os.name"));  
    System.out.println("操作系统的架构:" + System.getProperty("os.arch"));  
    System.out.println("操作系统的版本:" + System.getProperty("os.version"));  
    System.out.println("用户的账户名称:" + System.getProperty("user.name"));  
    System.out.println("用户的主目录:" + System.getProperty("user.home"));  
    System.out.println("用户的当前工作目录:" + System.getProperty("user.dir"));  
    System.out.println("文件分隔符:" + System.getProperty("file.separator"));  
    System.out.println("路径分隔符:" + System.getProperty("path.separator"));  
    System.out.println("行分隔符:" + System.getProperty("line.separator"));  
三、环境变量:
    System.out.println("所有用户Profile文件位置:"+System.getenv("ALLUSERSPROFILE"));  
    System.out.println("应用程序数据的默认存放位置:"+System.getenv("APPDATA"));  
    System.out.println("计算机名:"+System.getenv("COMPUTERNAME"));  
    System.out.println("x64常用文件的程序文件路径:"+System.getenv("CommonProgramFiles"));  
    System.out.println("x64常用文件的程序文件路径:"+System.getenv("CommonProgramW6432"));  
    System.out.println("指向 CMD.exe:"+System.getenv("COMSPEC"));  
    System.out.println("Windows系统所在磁盘分区:"+System.getenv("HOMEDRIVE"));  
    System.out.println("Windows系统所在磁盘分区:"+System.getenv("SYSTEMDRIVE"));  
    System.out.println("处理器内核数:"+System.getenv("NUMBER_OF_PROCESSORS"));  
    System.out.println("列出操作系统的名字。(WindowsXP和Windows2000列为Windows_NT.):"+System.getenv("OS"));  
    System.out.println("可执行文件的搜索路径:"+System.getenv("Path"));  
    System.out.println("默认可执行文件后缀:"+System.getenv("PATHEXT"));  
    System.out.println("处理器的芯片架构:"+System.getenv("PROCESSOR_ARCHITECTURE"));  
    System.out.println("计算机的处理器的型号:"+System.getenv("PROCESSOR_LEVEL"));  
    System.out.println("了处理器的修订号:"+System.getenv("PROCESSOR_REVISION"));  
    System.out.println("x64 ProgramFiles文件夹的路径:"+System.getenv("ProgramFiles"));  
    System.out.println("x64 ProgramFiles文件夹的路径:"+System.getenv("ProgramW6432"));  
    System.out.println("Windows系统所在的目录:"+System.getenv("SYSTEMROOT"));  
    System.out.println("Windows系统所在的目录:"+System.getenv("WinDir"));  
    System.out.println("当前登录的用户可用应用程序的默认临时目录:"+System.getenv("TEMP"));  
    System.out.println("当前登录的用户可用应用程序的默认临时目录:"+System.getenv("TMP"));  
    System.out.println("用户登录主机名:"+System.getenv("USERDOMAIN"));  
    System.out.println("当前登录的用户的名字:"+System.getenv("USERNAME"));  
    System.out.println("当前用户文件夹:"+System.getenv("USERPROFILE"));  
    System.out.println("当前用户文件夹:"+System.getenv("HOMEPATH"));  
    System.out.println("Windows目录位置:"+System.getenv("WINDIR"));  
    System.out.println("x86 ProgramFiles文件夹的路径:"+System.getenv("ProgramFiles(x86)"));  
    System.out.println("公共文件:"+System.getenv("PUBLIC"));  
    System.out.println("WindowsPowerShell模块路径:"+System.getenv("PSModulePath"));  
    System.out.println("登陆服务器名:"+System.getenv("LOGONSERVER"));  
    System.out.println("登陆的当前用户应用程序数据:"+System.getenv("LOCALAPPDATA"));

订阅博客

  • 我的CSDN博客 : 我的CSDN博客
  • 我的github资源: 我的github
  • 关注腾讯微博: 关注腾讯微博
  • 关注认证空间: 关注认证空间
  • 通过电子邮件订阅
  • 通过QQ邮件订阅

微信扫扫

  • 春华秋月

站内搜索

联系我们 投放广告 联系人:张宁 联系电话:18513780365 联系邮箱:master@pplns.com
本站采用创作共用版权协议, 要求署名、非商业用途和相同方式共享. 转载本站内容必须也遵循“署名-非商业用途-相同方式共享”的创作共用协议.