JAVA 笔记

一、Java基础以及面向对象编程
1、float类型的数自动转换成double类型时,可能会出现前后不相等的情况,因为有些数不能够用有限的二进制位精确表示。
2、右移
>>右移,左边空出位以符号位填充
>>>右移,左边空出位以0填充
3、计算阶乘

public class Factorial {
    public Factorial(){
        
    }
    public long getFactorial(int n){
        if((n<0)||(n>17)){
            return -1;
        }else if(n==0 || n==1){
            return 1;
        }else{
            long result=n;
            do{
                result *=(--n);
            }while(n>1);
            return result;
        }
    }
}

4、System.exit(0) 该方法关闭Java虚拟机,退出应用程序,当exit方法的参数为0时表示程序正常退出,为其他值时异常退出。
5、重写equals、clone、hashCode方法
这几个方法在Object类中都是基于对象的地址来实现的,如果要实现符合实际意义的方法,则需要在Object的子类中进行重写。这里以复数类为例:
(1)重写equals方法
先判断传入对象与现有对象是否同一类,再对同一类的传入对象比较属性。

    @Override
    public boolean equals(Object obj) {
        if(obj==null){
            return false;
        }
        if(obj instanceof ComplexNumber){
            ComplexNumber b=(ComplexNumber)obj;
            if((this.realPart == b.realPart) && (this.imaginaryPart==b.imaginaryPart)){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

(2)重写hashCode方法
找到一个能够代表对象的Key,如果这个key是int类型,可以直接返回该key,如果其他类型,则返回该key的hashCode。

    @Override
    public String toString() {
        return "ComplexNumber{" + "realPart=" + realPart + ", imaginaryPart=" + imaginaryPart + '}';
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

(3)重写clone方法
首先,类要实现Cloneable方法,然后再重写clone方法。实现时,先调用父类的clone方法,然后将现有对象的属性值赋给新对象。

    @Override
    protected Object clone() {
        try{
            ComplexNumber newObject=(ComplexNumber) super.clone();
            newObject.setRealPart(this.realPart);
            newObject.setImaginaryPart(this.imaginaryPart);
            return newObject;
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            return null;
        }
    }

6、Java在传递参数时,如果参数是对象类型,则将“参数的引用”复制之后传给方法。
7、System的gc方法通知Java虚拟机进行垃圾回收,但何时回收由虚拟机决定,进行垃圾回收时,虚拟机会调用对象的finalize方法。
8、对于每个类,Java虚拟机只加载一次,加载时,对类的静态方法、静态变量、静态初始化块进行初始化。只有在新建一个对象时,才会按先父类后子类的顺序初始化类的初始化块、构造函数。
9、方法和变量在继承时的覆盖和隐藏
(1)同名的实例方法被覆盖,同名的类方法(静态方法)被隐藏。
(2)隐藏和覆盖的区别:子类对象转换成父类后,能够访问父类被隐藏的变量和方法,但不能访问被覆盖的变量和方法。
10、排序
(1)接口

public interface ISortNumber {
    /**
     * 升序排序
     * @param intArray
     * @return 
     */
    public int[] sortASC(int[] intArray);
}

(2)选择排序

public class SelectionSort implements ISortNumber{

    public SelectionSort() {
    }

    @Override
    public int[] sortASC(int[] intArray) {
        if(intArray==null){
            return null;
        }
        
        int[] srcDatas=(int[])intArray.clone();
        int size=srcDatas.length;
        for(int i=0;i<size;i++){
            for(int j=i;j<size;j++){
                if(srcDatas[i]>srcDatas[j]){
                    swap(srcDatas,i,j);
                }
            }
        }
        return srcDatas;
    }
    
    private void swap(int[] data,int src,int dest){
        int temp=data[src];
        data[src]=data[dest];
        data[dest]=temp;
    }
}

(3)冒泡排序

public class BubbleSort implements ISortNumber{

    public BubbleSort() {
    }

    @Override
    public int[] sortASC(int[] intArray) {
        if(intArray==null){
            return null;
        }
        
        int[] srcDatas=(int[]) intArray.clone();
        boolean changedPosition=true;
        int comparedTimes=0;
        int maxComparedTimes=srcDatas.length-1;
        
        while((comparedTimes<maxComparedTimes) && (changedPosition)){
            for(int i=0;i<(maxComparedTimes-comparedTimes);i++){
                changedPosition=false;
                if(srcDatas[i]>srcDatas[i+1]){
                    swap(srcDatas,i,i+1);
                    changedPosition=true;
                }
            }
            comparedTimes++;
        }
        return srcDatas;
    }
    
    private void swap(int[] data,int src,int dest){
        int temp=data[src];
        data[src]=data[dest];
        data[dest]=temp;
    }
    
}

(4)线性插值排序

public class LinearInsertSort implements ISortNumber{

    public LinearInsertSort() {
    }

    @Override
    public int[] sortASC(int[] intArray) {
        if(intArray==null){
            return null;
        }
        int[] srcDatas=(int[])intArray.clone();
        int size=srcDatas.length;
        int temp=0;
        int index=0;
        for(int i=1;i<size;i++){
            temp=srcDatas[i];
            index=i;
            while((index>0) && (temp<srcDatas[index-1])){
                srcDatas[index]=srcDatas[index-1];
                index--;
            }
        }
        return srcDatas;
    }
    
}

(5)快速排序

public class QuickSort implements ISortNumber{

    public QuickSort() {
    }

    @Override
    public int[] sortASC(int[] intArray) {
        if(intArray==null){
            return null;
        }
        int[] srcDatas=(int[])intArray.clone();
        
        return this.quickSort(srcDatas,0,srcDatas.length-1);
    }
    
    private int[] quickSort(int[] srcDatas,int first,int last){
        if(first<last){
            int pos=partion(srcDatas,first,last);
            quickSort(srcDatas,first,pos-1);
            quickSort(srcDatas,pos+1,last);
        }
        return srcDatas;
    }
    
//根据数组的第一个数分治
//比第一个数大的往后排,比第一个数小的往前排
    private int partion(int[] srcDatas,int first,int last ){
        int temp=srcDatas[first];
        int pos=first;
        for(int i=first+1;i<=last;i++){
            if(srcDatas[i]<temp){
                pos++;
                swap(srcDatas,pos,i);
            }
        }
        swap(srcDatas,first,pos);
        return pos;
    }
    
     private void swap(int[] data,int src,int dest){
        int temp=data[src];
        data[src]=data[dest];
        data[dest]=temp;
    }
}

10、Singleton模式

(1)模式1

public class SingletonA {
    private static int id=1;
    private static SingletonA instance=new SingletonA();
    private SingletonA() {
        
    }
    
    public static SingletonA getInstance(){
        return instance;
    }
    
    public synchronized int getId(){
        return id;
    }
    
}

(2)模式2(lazy initialization)

public class SingletonA {
    private static int id=1;
    private static SingletonA instance=null;
    private SingletonA() {
        
    }
    
    public static SingletonA getInstance(){
        if(instance==null){
            instance=new SingletonA();
        }
        return instance;
    }
    
    public synchronized int getId(){
        return id;
    }
    
}

在getInstance方法声明中使用synchronized(同步)关键字,以保证同一时刻只有一个进程进入该方法。保证只创建一个对象。

11、Factory模式
(1)用一个接口抽象产品功能,所有具体的产品都实现该接口
(2)Factory类定义一个创建产品的方法,参数为产品的具体类型,返回一个产品接口对象。用户通过产品接口使用产品功能。
如下面的例子,该Factory类可以根据用户需求创建不同的用于排序的产品。

public class Factory {
    public static final String SELECTION_SORT="selection";
    public static final String BUBBLE_SORT="bubble";
    public static final String LINEARINSERT_SORT="linearinsert";
    public static final String QUICK_SORT="quick";
    
    public static ISortNumber getOrderNumber(String id){
        if(SELECTION_SORT.equalsIgnoreCase(id)){
            return new SelectionSort();
        }else if(BUBBLE_SORT.equalsIgnoreCase(id)){
            return new BubbleSort();
        }else if(LINEARINSERT_SORT.equalsIgnoreCase(id)){
            return new LinearInsertSort();
        }else if(QUICK_SORT.equalsIgnoreCase(id)){
            return new QuickSort();
        }else{
            return null;
        }
    }
    
}

12、Adapter类

public class Printer {
        public static void printIntArray(int[] array){
        if(array!=null){
            for(int i=0;i<array.length;i++){
                System.out.print(array[i]+" ");
            }
            System.out.println();
        }
    }
}

public class PrinterAdapter extends Printer implements ISortNumber{
    private ISortNumber mySort;

    public PrinterAdapter(ISortNumber mySort) {
        super();
        this.mySort = mySort;
    }
    
    @Override
    public int[] sortASC(int[] intArray) {
        if(this.mySort!=null){
            return this.mySort.sortASC(intArray);
        }
        return null;
    }
    
}

PrinterAdapter是Adapter,将Printer和ISortNumber进行适配,具有两者定义的所有功能。
ISortNumber是Adaptee。Adapter的构造方法中串入一个具体的Adaptee对象,在实现Adaptee接口定义的方法中,调用Adaptee的相应方法。
Printer是目标类。

二、数字
13、数字与数字封装类的相互转换
(1)byte与Byte

byte b1=5;
Byte b2=new Byte(b1); //或者 Byte b2=Byte.valueOf(b1);
byte b3=b2.byteValue();

(2)int与Integer

int i1=5;
Integer i2=new Integer(i1);//或者 Integer i2=Integer.valueof(i1);
int i3=i2.intValue();

14、格式化数字,使用DecimalFormat类。

DecimalFormat df=new DecimalFormat();
double data=1234.4650238903;
String pattern="0.0";//显示格式
df.applyPattern(pattern);
String str=df.format(data);//格式化后为1234.5
//pattern ="00000.000 kg" 格式化为001234.465 kg
//pattern ="##000.000 kg" 格式化为1234.465 kg
//pattern ="-000.000" 格式化为-1234.465
//pattern ="-0,000.000" 格式化为-1,234.465
//pattern ="0.00E000" 格式化为1.23E003
//pattern ="0.00%" 格式化为123446.50%
//pattern ="0.00\u2030" 格式化为1234465.02‰,显示为千分数

15、数字的舍入
用BigDecimal类的setScale方法来实现,支持不同的舍入模式。
16、数制的转换
Integer或Long的toString(int i,int radix)、toBinaryString()、toOctalString()、toHexString()等方法。
17、生成随机数,用Random类来实现。
18、高精度运算
使用BigInteger和BigDecimal类。
下例,计算阶乘。

     public BigInteger getFactorial(int n){
        if((n<0)||(n>17)){
            return new BigInteger("-1");
        }else if(n==0 || n==1){
            return new BigInteger("1");
        }else{
            BigInteger result=new BigInteger("n");
            do{
                result.multiply(new BigInteger(new Integer(--n).toString()));
            }while(n>1);
            return result;
        }
    }

BigInteger和BigDecimal类都是不可变的,每一步运算都会产生一个新对象,不适合大量的数学运算。这两个类常常用在商业计算的精确大整数和小数。
要获得精确小数,应使用String来构造BigDecimal,避免使用double来构造,因为double类型并不精确。
从数值上比较两个BigDecimal的值时,应使用compareTo方法,而不是equals方法,因为后者会认为0.10和0.1不相等。

三、数组与集合
1、Arrays
填充数组,

int[] array0=new int[10];
Arrays.fill(array0,3);//给数组所有元素赋值为5
Arrays.fill(array0,2,5,7);//给array0[2]~array0[4]赋值为7

排序

Arrays.sort(array0,2,7);//将array0[2]~array0[6]排序
Arrays.sort(array0);//整个数组排序

2、求质数

    /**
     * 用筛选法求range范围内的质数
     * @param range 范围的上限
     * @return 
     */
    private boolean[] sieve(int range){
        if(range<0){
            return null;
        }
        
        boolean[] isPrime=new boolean[range+1];
        isPrime[1]=false;
        Arrays.fill(isPrime, 2, range+1, true);
        
        int n=(int)Math.sqrt(range);
        for(int i=1;i<=n;i++){
            if(isPrime[i]){
                //如果i是质数,则i的倍数不是质数
                for(int j=2*i;j<=range;j+=i){
                    isPrime[j]=false;
                }
            }
        }
        return isPrime;
    }

3、动态调整数组的长度
新建一个新的数组,然后将原数组的数据拷贝到新数组中。
Integer[] result=new Integer[src.length+length];
System.arraycopy(src,0,result,0,src.length);
4、矩阵
用double二维数组创建矩阵,并实现矩阵的加减乘除算法。

  1 public class Matrix implements Cloneable{
  2     private double[][] matrixData;
  3 
  4     public Matrix() {
  5         this.init();
  6     }
  7 
  8     public Matrix(double[][] matrixData) {
  9         if(!this.canConvert2Matrix(matrixData)){
 10             this.init();
 11         } else{
 12             this.matrixData = this.cloneArray(matrixData);
 13         }
 14     }
 15     
 16     private void init(){
 17         this.matrixData=new double[][]{
 18             {1.0,0.0,0.0},
 19             {0.0,1.0,0.0},
 20             {0.0,0.0,1.0}};
 21     }
 22     
 23     private boolean canConvert2Matrix(double[][] matrixData){
 24         if(matrixData==null){
 25             return false;
 26         }
 27         for(int i=0;i<matrixData.length-1;i++){
 28             if(matrixData[i].length!=matrixData[i+1].length){
 29                 return false;
 30             }
 31         }
 32         return true;
 33     }
 34     
 35     private double[][] cloneArray(double[][] src){
 36         if(src==null){
 37             return null;
 38         }
 39         return (double[][]) src.clone();
 40     }
 41     /**
 42      * 矩阵相加
 43      * @param b
 44      * @return 
 45      */
 46     public Matrix add(Matrix b){
 47         if(b==null){
 48             return null;
 49         }
 50         
 51         Matrix c=null;
 52         double[][] bData=b.getMatrixData();
 53         if(this.matrixData.length!=bData.length
 54                 || this.matrixData[0].length!=bData[0].length){
 55             System.out.println("两个矩阵长度不一致,不能相加");
 56             return c;
 57         }
 58         
 59         double[][] cData=new double[this.matrixData.length][this.matrixData[0].length];
 60         for(int i=0;i<this.matrixData.length;i++){
 61             for(int j=0;j<this.matrixData[0].length;j++){
 62                 cData[i][j]=this.matrixData[i][j]+bData[i][j];
 63             }
 64         }
 65         c=new Matrix(cData);
 66         return c;
 67         
 68     }
 69     
 70    /**
 71      * 矩阵相减
 72      * @param b
 73      * @return 
 74      */
 75     public Matrix sub(Matrix b){
 76         if(b==null){
 77             return null;
 78         }
 79         
 80         Matrix c=null;
 81         double[][] bData=b.getMatrixData();
 82         if(this.matrixData.length!=bData.length
 83                 || this.matrixData[0].length!=bData[0].length){
 84             System.out.println("两个矩阵长度不一致,不能相减");
 85             return c;
 86         }
 87         
 88         double[][] cData=new double[this.matrixData.length][this.matrixData[0].length];
 89         for(int i=0;i<this.matrixData.length;i++){
 90             for(int j=0;j<this.matrixData[0].length;j++){
 91                 cData[i][j]=this.matrixData[i][j]-bData[i][j];
 92             }
 93         }
 94         c=new Matrix(cData);
 95         return c;
 96         
 97     }
 98     
 99     /**
100      * 矩阵数乘
101      * @param num
102      * @return 
103      */
104     public Matrix multiplyNum(double num){
105         double[][] cData=new double[this.matrixData.length][this.matrixData[0].length];
106         for(int i=0;i<this.matrixData.length;i++){
107             for(int j=0;j<this.matrixData[0].length;j++){
108                 cData[i][j]=this.matrixData[i][j] * num;
109             }
110         }
111         return new Matrix(cData);
112     }
113     
114         
115     /**
116      * 矩阵乘法
117      * @param b
118      * @return 
119      */
120     public Matrix multiply(Matrix b){
121         if(b==null)
122             return null;
123         double[][] bData=b.getMatrixData();
124         if(this.matrixData[0].length!=bData.length){
125             System.out.println("矩阵的A的列数不等于矩阵B的行数,不能相乘");
126             return null;
127         }
128         double[][] cData=new double[this.matrixData.length][bData[0].length];
129         for(int i=0;i<this.matrixData.length;i++){
130             for(int j=0;j<bData[0].length;j++){
131                 cData[i][j]=0;
132                 for(int k=0;k<this.matrixData[0].length;k++){
133                     cData[i][j]+=this.matrixData[i][k]*bData[k][j];
134                 }
135             }
136         }
137         return new Matrix(cData);
138     }
139     
140     /**
141      * 矩阵除法
142      * @param b
143      * @return 
144      */
145     public Matrix divide(Matrix b){
146         if(b==null){
147             return null;
148         }
149         if(!this.isSquareMatrix() 
150                 || (!b.isSquareMatrix())
151                 || (this.matrixData.length!=b.getMatrixData().length)){
152             System.out.println("不能相除");
153             return null;
154         }
155         Matrix c=b.inverseMatrix();
156         if(c!=null)
157             return this.multiply(c);
158         else{
159             System.out.println("不能相除");
160             return null;
161         }
162     }
163     /**
164      * 逆矩阵
165      * @return 
166      */
167     public Matrix inverseMatrix() {
168         if(!this.isSquareMatrix()){
169             System.out.println("不是方阵,不能求逆");
170             return null;
171         }
172         
173         Matrix tempM=this.appendUnitMatrix();
174         double[][] tempData=tempM.getMatrixData();
175         int line=0;
176         double bs=0;
177         double swap=0;
178         for(int i=0;i<tempData.length;i++){
179             if(tempData[i][i]==0){
180                 if(++line>=tempData.length){
181                     System.out.println("没有逆矩阵");
182                     return null;
183                 }
184                 for(int j=0;j<tempData[0].length;j++){
185                     swap=tempData[i][j];
186                     tempData[i][j]=tempData[line][j];
187                     tempData[line][j]=swap;
188                 }
189                 continue;
190             }
191             
192             if(tempData[i][i]!=1){
193                 bs=tempData[i][i];
194                 for(int j=tempData[0].length-1;j>=0;j--){
195                     tempData[i][j]/=bs;
196                 }
197                 for(int iNow=i+1;iNow<tempData.length;iNow++){
198                     for(int j=tempData[0].length-1;j>=i;j--){
199                         tempData[iNow][j]-=tempData[i][j]*tempData[iNow][i];
200                     }
201                 }
202             }
203         }
204         //将左边矩阵变为单位矩阵
205         for(int i=0;i<tempData.length-1;i++){
206             for(int iNow=i;iNow<tempData.length-1;iNow++){
207                 for(int j=tempData[0].length-1;j>=0;j--){
208                     tempData[i][j]-=tempData[i][iNow+1]*tempData[iNow+1][j];
209                 }
210             }
211         }
212         
213         //右边部分为逆矩阵
214         double[][] cData=new double[this.matrixData.length][this.matrixData[0].length];
215         for(int i=0;i<this.matrixData.length;i++){
216             for(int j=0;j<this.matrixData[0].length;j++){
217                 cData[i][j] =tempData[i][j+this.matrixData[0].length];
218             }
219         }
220         return new Matrix(cData);
221     }  
222     /**
223      * 给矩阵右边加上单位矩阵
224      * @return 
225      */
226     private Matrix appendUnitMatrix(){
227         double[][] cData=new double[this.matrixData.length][this.matrixData[0].length*2];
228         for(int i=0;i<this.matrixData.length;i++){
229             for(int j=0;j<this.matrixData[0].length*2;j++){
230                 if(j<this.matrixData[0].length){
231                     cData[i][j]=this.matrixData[i][j];
232                 }else{
233                     if((j-this.matrixData[0].length)==i){
234                         cData[i][j]=1.0;
235                     }else{
236                         cData[i][j]=0.0;
237                     }
238                 }
239             }
240         }
241         return new Matrix(cData);
242     }
243     
244     /**
245      * 转置矩阵
246      * @return 
247      */
248     public Matrix transposeMatrix(){
249         double[][] cData=new double[this.matrixData[0].length][this.matrixData.length];
250         for(int i=0;i<this.matrixData[0].length;i++){
251             for(int j=0;j<this.matrixData.length;j++){
252                 cData[i][j]=this.matrixData[j][i];
253             }
254         }
255         return new Matrix(cData);
256     }
257     
258     /**
259      * 矩阵是否为方阵
260      * @return 
261      */
262     public boolean isSquareMatrix(){
263         if(this.matrixData.length==this.matrixData[0].length){
264             return true;
265         }
266         return false;
267     }
268     
269     public double[][] getMatrixData(){
270         return this.cloneArray(this.matrixData);
271     }
272 
273     public void setMatrixData(double[][] matrixData){
274         if(this.canConvert2Matrix(matrixData)){
275             this.matrixData=this.cloneArray(matrixData);
276         }
277     }
278 
279     @Override
280     public String toString() {
281         DecimalFormat df=new DecimalFormat("0.00");
282         StringBuffer sb=new StringBuffer("");
283         for(int i=0;i<this.matrixData.length;i++){
284             for(int j=0;j<this.matrixData[0].length;j++){
285                 sb.append(df.format(this.matrixData[i][j])).append(" ");
286             }
287             sb.append("\n");
288         }
289         return sb.toString();
290     }
291 
292     @Override
293     public int hashCode() {
294         return this.toString().hashCode();
295     }
296 
297     @Override
298     public boolean equals(Object obj) {
299         if (obj == null) {
300             return false;
301         }
302         if (getClass() != obj.getClass()) {
303             return false;
304         }
305         final Matrix other = (Matrix) obj;
306         if (!Arrays.deepEquals(this.matrixData, other.matrixData)) {
307             return false;
308         }
309         return true;
310     }
311 
312     @Override
313     protected Object clone(){
314         try{
315             Matrix matrix=(Matrix) super.clone();
316             matrix.setMatrixData(this.matrixData);
317             return matrix;
318         }catch(CloneNotSupportedException e){
319         }
320         return null;
321     }
322 }
View Code

5、ArrayList、Vector和LinkedList
(1)ArrayList、Vector都是用数组实现,不同的是Vector支持线程同步
(2)LinkedList使用链表结构存储数据,方便操作列表头和列表尾元素。
(3)可以为List生成ListIterator,支持双向遍历。
6、生成不重复的随机数序列
(1)排除法
如果新生成的数字不包含在结果列表中,则将数字添加到列表,否则,重新生成随机数。
(2)筛选法
将所有可能的数字放到候选列表中,将生成的随机数k作为下标,对应的候选列表中的数字添加到结果列表中,并从候选列表中删除。
7、用LinkedList可以方便地实现Queue
8、对List进行排序,用Collections.sort()方法,可以设置自定义的比较器(实现Comparator接口)。
9、HashSet
采用散列函数对元素进行排序。存入HashSet中的对象必须定义hashCode方法。
10、TreeSet
采用红黑树的数据结构进行排序,可以提取有序的序列。存入TreeSet中的自定义类对象需要实现Comparable接口并定义compareTo方法。
11、LinkedHashSet
使用链表维护元素的插入次序。元素的次序就是插入时的次序。
12、数组、List和Set之间的相互转化
(1)List转化为数组

String[] strArray=(String[])list.toArray(new String[list.size()]);

(2)Set转化为数组

String[] strArray=(String[])set.toArray(new String[set.size()]);

(3)数组转化为List

list=Arrays.asList(strArray);

(4)数组转化为Set,先转为List,再构造Set

set=new HashSet(Arrays.asList(strArray));

13、Map 键值对存储
(1)HashMap
不支持线程同步,键或值可以为null。
(2)HashTable
键或值都不能为null。支持线程同步。
(3)LinkedHashMap
保存记录的插入次序。
(4)TreeMap
记录按照Key来排序。
14、对Map排序
(1)其他Map转换成TreeMap,便可以进行按Key排序。
(2)TreeMap默认升序排列,可以指定比较器。
15、Properties属性文件
能从输入流(文件)中获取键值对信息,也可以将键值对信息存放到输出流(文件)中。

Properties props=new Properties();
//存放数据
props.setProperty("name","zhangsan");
//读取数据
String str=props.getProperty("name");
//保存到输出流
FileOutputStream out=new FileOutputStream("C:/test.properties");
props.store(out,"test");
out.close();
//从输出流中加载数据
Properties newProps=new Properties();
FileInputStream in=new FileInputStream("C:/test.properties");
newProps,load(in);
in.close();

四、字符串
1、String是不变类,修改String会得到新的String对象,如果要频繁修改字符串,应使用StringBuilder类。
2、IP地址转换为整数

     public static long ipToLong(String strIP){
        long[] ip=new long[4];
        int position1=strIP.indexOf(".");
        int position2=strIP.indexOf(".",position1+1);
        int position3=strIP.indexOf(".",position2+1);
        ip[0]=Long.parseLong(strIP.substring(0, position1));
        ip[1]=Long.parseLong(strIP.substring(position1+1, position2));
        ip[2]=Long.parseLong(strIP.substring(position2+1, position3));
        ip[3]=Long.parseLong(strIP.substring(position3+1));
        
        return (ip[0]<<24)+(ip[1]<<16)+(ip[2]<<8)+ip[3];
    }
    
    public static String longToIP(long longIP){
        StringBuilder sb=new StringBuilder("");
        sb.append(String.valueOf(longIP>>>24)).append(".");
        sb.append(String.valueOf((longIP&0x00FFFFFF)>>>16)).append(".");
        sb.append(String.valueOf((longIP&0x0000FFFF)>>>8)).append(".");
        sb.append(String.valueOf(longIP&0x000000FF));
        return sb.toString();
    }     

3、更改字符串的编码
先调用String的getBytes方法对字符串进行解码,再用得到的字节数组和新的字符编码构造一个新的String对象。
4、对字符串进行MD5编码
MD5是一种不可逆的加密方式,常用于管理账户信息数据库,数据库存储的是用户密码的MD5编码,这样可以防止用户的密码信息被管理员知道。

    public static String encodeByMD5(String originString){
        String[] hexDigits={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
        if(originString!=null){
            try{
                MessageDigest md=MessageDigest.getInstance("MD5");
                byte[] result=md.digest(originString.getBytes());
                
                StringBuilder sb=new StringBuilder();
                for(int i=0;i<result.length;i++){
                    int n=result[i];
                    if(n<0)
                        n=256+n;
                    int d1=n/16;
                    int d2=n%16;
                    sb.append(hexDigits[d1]+hexDigits[d2]);
                }
                return sb.toString();
            }catch(Exception e){
                
            }
        }
        return null;
    }

5、制作命令行程序
难点在于解析命令行参数,可以使用Apache组织的cli项目的类库来完成。
6、StringTokenizer可以使字符串分写成多个标记。
7、使用正则表达式操作字符串
(1)java.util.regex.Pattern类 对正则表达式字符串进行编译
(2)java.util.regex.Matcher类,通过解释Pattern对字符串进行匹配,find方法返回查找匹配的结果,matches方法返回精确匹配的结果。
8、使用正则表达式验证电话号码格式

public static boolean isMatch(String phoneNum){
        String patternStr="^([0-9]{3}-?[0-9]{8}) |([0-9]{4}-?[0-9]{7})$";
        if(phoneNum!=null){
            return phoneNum.matches(patternStr);
        }
        return false;
    }

五、异常处理
1、避免使用异常
可以提前检测语句的使用条件,避免异常出现
2、不要为每个可能出现异常的语句单独设置try catch,尽量将这些语句都放在一个try块中。
3、避免在方法中抛出或捕获RuntimeException和Error
4、尽量catch具体的异常,不要总是catch Exception
5、不能处理的异常要往外抛
6、不要在循环体中使用try...catch

六、线程
1、线程的互斥
在某一个时刻,只允许一个线程访问对象的临界区 。如果一个对象有多个方法都要修改同一个变量的值,应将这些方法置为synchronized。
2、线程协作
wait、notify、notifyAll等关键字必须放在synchronized代码块中。

static class Printer extends Thread{
        Vector task=new Vector();
        boolean running=false;
        public void start(){
            this.running=true;
            super.start();
        }

        @Override
        public void run() {
            try{
                while(running){
                    synchronized(this){
                        while((task.size()==0)&&running){
                            //如果任务为空,线程允许运行,则等待任务
                            //进入等待状态,释放对象锁
                            wait();
                        }
                    }
                    //执行任务
                    System.out.println("print the task:"+task.remove(0));
                }
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        //添加打印任务
        public void adddTask(String str){
            synchronized(this){
                this.task.add(str);
                //唤醒等待的线程
                notify();
            }
        }
        //停止线程
        public void stopPrinter(){
            this.running=false;
            synchronized(this){
                //唤醒其他等待的线程
                notify();
            }
        }
    }

3、join
调用子线程的join方法,表示当前线程必须等待子线程运行结束,才能继续运行。
4、消费者与生产者
用线程模拟消费者和生产者,不断从仓库类中消费/生产产品。
在仓库类中,消费产品时,如果产品数量为0,则wait,使消费线程等待,当有新产品存入时,notify,唤醒等待的消费线程。同理,生产产品时,如果产品数量达到上限,则wait,使生产线程等待,当有产品被消费后,notify,唤醒等待的生产线程。
注意:调用某个对象的wait、notify、notifyAll等方法时,必须用synchronized先获得对象锁,否则会抛出IllegalMonitorStateException异常。

  1 //(1)产品
  2 public class Product {
  3     private String name;
  4 
  5     public Product(String name) {
  6         this.name = name;
  7     }
  8 }
  9 //(2)消费者线程
 10 public class Consumer extends Thread {
 11     private Warehouse warehouse;
 12     private boolean running=false;
 13 
 14     public Consumer(Warehouse warehouse, String name) {
 15         super(name);
 16         this.warehouse = warehouse;
 17     }
 18 
 19     public boolean isRunning() {
 20         return running;
 21     }
 22 
 23     @Override
 24     public synchronized void start() {
 25         this.running=true;
 26         super.start(); 
 27     }
 28         
 29     @Override
 30     public void run() {
 31         Product product;
 32         try{
 33             while(running){
 34                 product=warehouse.getProduct();
 35                 sleep(500);
 36             }
 37         }catch(InterruptedException e){
 38             e.printStackTrace();
 39         }
 40     }
 41     
 42     public void stopConsumer(){
 43         synchronized(warehouse){
 44             this.running=false;
 45             warehouse.notifyAll();
 46         }
 47     }
 48 }
 49 //(3)生产者线程
 50 public class Producer extends Thread{
 51 
 52     private Warehouse warehouse;
 53     private static int productName=0;
 54     private boolean running=false;
 55 
 56     public Producer(Warehouse warehouse, String name) {
 57         super(name);
 58         this.warehouse = warehouse;
 59     }
 60 
 61     public boolean isRunning() {
 62         return running;
 63     }
 64 
 65     @Override
 66     public synchronized void start() {
 67         this.running=true;
 68         super.start(); 
 69     }
 70         
 71     @Override
 72     public void run() {
 73         Product product;
 74         try{
 75             while(running){
 76                 product=new Product("pro"+(++productName));
 77                 this.warehouse.storageProduct(product);
 78                 sleep(300);
 79             }
 80         }catch(InterruptedException e){
 81             e.printStackTrace();
 82         }
 83     }
 84     
 85     
 86     public void stopProducer(){
 87         synchronized(warehouse){
 88             this.running=false;
 89             warehouse.notifyAll();
 90         }
 91     }
 92     
 93 }
 94 //(4)仓库类
 95 public class Warehouse {
 96     private static int CAPACITY=11;//仓库容量
 97     private Product[] products;
 98     
 99     private int front=0;//当前第一个未被消费的产品下标
100     private int rear=0;//当前最后一个未被消费的产品下标+1;
101 
102     public Warehouse() {
103         this.products = new Product[CAPACITY];
104     }
105 
106     public Warehouse(int capacity) {
107         this();
108         if(capacity>0){
109             CAPACITY=capacity+1;
110             this.products = new Product[CAPACITY];
111         }
112     }
113 
114     public Product getProduct() throws InterruptedException {
115         synchronized(this){
116             boolean consumerRunning=true;
117             Thread currentThread=Thread.currentThread();
118             if(currentThread instanceof Consumer){
119                 consumerRunning=((Consumer)currentThread).isRunning();
120             }else{
121                 return null;
122             }
123             //仓库中没有产品,则消费线程等待
124             while((front==rear) && consumerRunning){
125                 wait();
126                 consumerRunning=((Consumer)currentThread).isRunning();
127             }
128             
129             if(!consumerRunning){
130                 return null;
131             }
132             
133             Product product=products[front];
134             front=(front+1+CAPACITY) % CAPACITY;
135             System.out.println("Concumer"+Thread.currentThread().getName());
136             System.out.println("剩余产品"+(rear+CAPACITY-front)%CAPACITY);
137             notify();
138             return product;
139         }
140     }
141     
142     public void storageProduct(Product product) throws InterruptedException {
143         synchronized(this){
144             boolean producerRunning=true;
145             Thread currentThread=Thread.currentThread();
146             if(currentThread instanceof Producer){
147                 producerRunning=((Producer)currentThread).isRunning();
148             }else{
149                 return;
150             }
151             //仓库中没有产品,则消费线程等待
152             while(((rear+1)%CAPACITY==front) && producerRunning){
153                 wait();
154                 producerRunning=((Producer)currentThread).isRunning();
155             }
156             
157             if(!producerRunning){
158                 return;
159             }
160             
161             products[rear]=product;
162             rear=(rear+1)%CAPACITY;
163             System.out.println("Producer"+Thread.currentThread().getName());
164             System.out.println("剩余产品"+(rear+CAPACITY-front)%CAPACITY);
165             notify();
166         }
167     }
168     
169 }
View Code

5、两个同时启动的线程,通常优先级高的线程会先运行。
6、守护线程(Daemon线程)
Thread的setDaemon方法设置线程是否为守护线程。必须在调用start之前调用该方法,否则无效。
只有当程序中所有的非守护线程都结束时,守护线程才会无条件地立即结束,并且不会调用finally中的语句。
7、线程池
将执行某一类任务的线程放在线程池中,有任务要执行时,从池中取出一个空闲线程来处理任务,处理结束后,再将线程池放入池中。
自定义线程池
(1)任务接口

public interface Task {
    public void perform() throws Exception;
}

(2)自定义任务类

public class MyTask implements Task {
    private int taskId=0;

    public MyTask(int id) {
        this.taskId=id;
    }

    @Override
    public void perform() throws Exception {
        System.out.println("task "+taskId+" begin");
        try{
            Thread.sleep(1000);
        }catch(InterruptedException e){
        }
        System.out.println("task "+taskId+" end");
    }
}

(3)线程池

public class MyThreadPool extends ThreadGroup{
    private boolean isAlive;
    private LinkedList taskQueue;
    private int threadId;
    private static int threadPoolId;

    public MyThreadPool(int numThreads) {
        super("ThreadPool-"+(threadPoolId++));
        super.setDaemon(true); //线程池中所有线程被销毁时,线程池自动销毁
        this.isAlive=true;
        this.taskQueue=new LinkedList();
        for(int i=0;i<numThreads;i++){
            new PooledThread().start();
        }
    }
    //内部类,工作线程
    private class PooledThread extends Thread{

        public PooledThread() {
            super(MyThreadPool.this,"PooledThread-"+(threadId++));
        }

        @Override
        public void run() {
            while(!isInterrupted()){
                Task task=null;
                try{
                    task=getTask();
                }catch(InterruptedException e){
                    
                }
                if(task==null){
                    return;
                }
                try{
                    task.perform();
                }catch(Throwable t){
                    uncaughtException(this,t);
                }
            }
        }
    }
    
    protected synchronized Task getTask() throws InterruptedException{
        if(!this.isAlive){
            return null;
        }
        while(this.taskQueue.size()==0){
            wait();
        }
        return (Task)this.taskQueue.removeFirst();
    }
    
    public synchronized void performTask(Task task){
        if(!this.isAlive){
            throw new IllegalStateException();
        }
        if(task!=null){
            this.taskQueue.add(task);
            notify();
        }
    }
     //关闭线程池,所有线程停止,不再执行任务
    public synchronized void close(){
        if(isAlive){
            this.isAlive=false;
            this.taskQueue.clear();
            this.interrupt();
        }
    }
    
    //关闭线程池,等待所有任务执行完成
    public void join(){
        synchronized(this){
            this.isAlive=false;
            this.notifyAll();
        }
        
        Thread[] threads=new Thread[this.activeCount()];
        //将线程池中活动线程拷贝到新的线程组中
        int count=this.enumerate(threads);
        for(int i=0;i<count;i++){
            try{
                threads[i].join();
            }catch(InterruptedException e){
            }
        }
    }
}

8、当线程进入对象的synchronized代码块时,占有了该资源,直到退出该代码块或者调用wait方法,才会释放该资源,在此期间,其他线程将不能进入该代码块。synchronized尝试占有对象资源,如果不能占有,将一直等待。
线程相互占有对方等待的资源且都不主动释放所占有的资源时,将发生线程死锁。
9、定时器的使用
(1)实现一个继承TimerTask抽象类的自定义类MyTimerTask
(2)结合Timer实现定时执行任务的功能

Timer timer=new Timer();
TimerTask myTask1=new MyTimerTask();
timer.schedule(myTask1,200,300);//200ms后执行myTask1,之后每隔300ms执行一次myTask1

(3)中止定时任务

timer.cancle();

六、反射
1、反射(Reflection)允许Java程序对自身进行检查,并能直接操作程序的内部属性。
2、instanceof 在运行时判断对象的类型
3、java.lang.reflect包实现了java的反射机制。

七、网络编程
1、URL通信
2、Socket通信
3、UDP通信

posted @ 2015-09-18 08:50  庭庭小妖  阅读(230)  评论(0编辑  收藏  举报