java基础语法要点<一>(基于1.8)

 

http://yishouce.com/java/run

http://www.shucunwang.com/RunCode/java/

数据类型

8种基本数据类型及对应的 类型封装器

  byte, short, int, long ->  Long,Integer,Short,Byte :Number 

  float, double   ->  Double,Float :Number 

  char, boolean -> Character,Boolean

java中其他数据类型都是由类封装,但基本数据类型不是,和c,c++一样,基本数据类型仅表示单个值,因为将基本数据类型设计为对象会极大地降低性能。

  类型封装器:基本类型提供了性能方面的好处,但有时会需要对象的表现形式:传递引用及许多数据结构都是针对对象进行操作的。   

     数值类型封装器都继承自抽象类Number

Integer(int num)
Integer(String str)   // NumberFormatException

Integer iob = new Integer(100);
int i = iob.intValue();

// 从jdk 5开始,增加了两个重要特性,自动装箱和自动拆箱。
// 极大地简化了一些算法代码,也有助于防止出错,对泛型,集合框架非常重要。

Integer iob = 100;
int i = iob;

 

整型

  • java的int总是32位,不随平台而变化。
  • 没有无符号整数,增加了“无符号右移”运算符。
  • 增加8位整型 byte,方便操作数据流及原始二进制数据。
    public class test {
    	public static void main(String[] args) {
    		Integer a = -129;
    		Integer b = -129;
    		System.out.println(a == b); //false
    
                   //Integer 直接缓存了 -128~127之间的数,原因是这些100内的数使用频度极高
                   //所以下例中 a == b是true,是因为它们确实指向了同一个实例
    		a = 1;
    		b = 1;
    		System.out.println(a == b); //true
    
    		a = 128;
    		b = 128;
    		System.out.println(a == b); //false
    		
    		int m = 1;
    		float n = 2.1f;
    		m+=n;  // m = (int)m+n;
    		System.out.println(m); // 3
    		//m = m + n;   报错,不能把float赋值给int
    	}
    }
    
    float a=3;
    double b=2;
    
    b+=a;
    b=b+a;
    a+=b;
    a=a+b;  //报错, a+b时会自动把a提升为double,而double类型不能直接赋值给float
    a=(float)(a+b)
    
    // int类型的值 和 float类型的值相加,得到的结果是float而不是double
    int a =1;
    float b = 6;
    b = b +a;
    

     16进制的字面量0x做前缀,8进制的字面量0做前缀

字符型char为16位

  • java使用unicode表示字符,char为16位(一个unicode标量的宽度)
  • 取值范围 0 ~ 65536
  • java中 char 同c 一样 可以做整型使用
    char ch1,ch2;
    ch1 = 88;
    ch2 = 'x';
    System.out.println(ch1);       // X
    System.out.println(ch2);       // x
    System.out.println(++ch1);     // Y
    System.out.println(++ch2);     // y

数组

 java中只有动态数组,同时会严格检查数组下标,避免越界。

 java中的数组是作为类的对象实现的。 

// 申请内存与c++相同,但无需delete操作
int x[] = new int[12];
       
// 也可以直接初始化,java会自动创建足够大的数组,以容纳数组初始化器里的元素
int days[] = {31,28,31,30,31,30,31};
       
// 多维数组
int twoD[][] = new int[4][5];

// 手动分配第二维
int twoD2[][] = new int[4][];
twoD2[0] = new int[1];
twoD2[1] = new int[2];
twoD2[2] = new int[3];
twoD2[3] = new int[4];

// 初始化器
int twoD3[][] = {
    	{1,2},
    	{1,2,3},
    	{1,2,3,4}
};
       
       
// 另一种数组声明语法
int[] y = new int[12]; //int x[] = new int[12];
int[][] twoD4 = new int[4][5];//twoD[][] = new int[4][5];

 在java中数组也是由类实现的,数组创建后如果没有初始化数据,则都会是默认值,即布尔类型默认为false,数值默认为0,其他默认为null。

public static void main(……){
    int arr[] = {11  , 22  , 33};
    Object nnn = arr;
    chageArrA((int[])nnn);
    System.out.println(arr[1]);   //  44
		
    if (nnn instanceof int[]){
	System.out.println("OK");  // OK
    }
}

public  static  void chageArrA(int[] name){
    name[1] = 44;
}

 

String

  1. 在java string不是关键字也不是保留字
  2. 每个字符串都是String的对象。
  3. 字符串对象是不可变的,修改字符串实际是创建了一个新的对象。
  4. 大量的字符串拼接操作,使用 StringBuffer和StringBuilder,它们是String的对等类,但它们允许修改字符串。
  5. 常用属性,方法: length, equals(), charAt()
  6. 命令行参数  main(String args[]){} 
class CommandLine{
    public static void main(String args[]){
        for(int i=0; i< args.length;i++){
            System.out.println("args["+i+"] : " + args[i]);
        }
    }
}

// java CommandLine this is a test 100 - 1

 

public class test {
	public static void main(String[] args) {
               //java中的String类 在创建后就不可再被更改,所以其本身是线程安全的
               //对于字符串直接量,JVM会使用一个字符串驻留池来缓存它们,一般情况下字符串驻留池里的字符串对象不会被GC回收,当再次使用驻留池中已有的字符串对象时,就无需再次创建了。
		String aa = "32@#@";
		String bb = "32@#@";
		System.out.println(aa == bb);//true
		
		String cc = new String("32@#@");
		System.out.println(aa == cc);//false
		
		//主动使用字符串驻留池,如果池中已有一个等于此字符串的对象(equals(Object)),
		//则返回池中的字符串,否则,将此字符串添加到池中,并返回引用
		cc = cc.intern();
		System.out.println(aa == cc);//true
	}
}

 

不支持指针

 java 中不支持程序员操作指针,因为指针可能突破java执行环境和宿主计算机之间的防火墙,操作java运行时系统之外的地址。这与java的设计理念不合。

 同时因为引用对象的变量的传递,实质是对指针的拷贝,所以java中没有真正的引用传递操作,因为JAVA认为没有指针也足够满足用户的需求。而c#中则可以使用ref。

public class test {
        // change不是在改变传入对象的状态,而是改了str的指向
	public static void change(String str){
		str = "aaa";
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s = "1223";
		change(s);
		System.out.println(s);
	}
}
// 结果: 1223, 
// String 是类实现,属于引用传递,但在change方法中,str指向了一个新的实例,而不是修改传入的那个实例

 

运算符

>>>

 按位右移 补0 (对某些非数值的数据进行移位操作时,并不希望出现符号扩展)

instanceof 

判别对象是否是某类的实例

不短路的布尔逻辑运算

&,|

 

运算符分类 

算数运算符:

+,-,*, / , %, ++, --, +=,-=,*=,/=,%=

位运算符:

~,&,|,^,>>, >>>, <<, &=, |= , ^= , >>= , >>>=, <<=

关系运算符:

==,!=,>,<,>=,<=

布尔逻辑运算符:

&,|,^, ||, &&,!,&=,|=,^=,==,!=,?:

赋值运算符:

没有运算符重载

equals与==

类的比较要用equals, 而不能用==,后者比较的是两个地址,即是恒等于

整型是会溢出的,所以有 i + 1< i 可能成立

同样 x>y||x<=y 也可能不成立,因为有NAN的存在

Double x = Double.NaN;
Float y = Float.NaN;
if(!(x>y||x<=y)){
	System.out.println("ok");
}
		

 

类 

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)

public class Singleton {
    // 静态变量
    public static String staticField = "静态变量";
    // 变量
    public String field = "变量";

    // 静态初始化块
    static {
        System.out.println(staticField);
        System.out.println("静态初始化块");
    }

    // 初始化块
    {
        System.out.println(field);
        System.out.println("初始化块");
    }

    // 构造器
    public Singleton() {
        System.out.println("构造器");
    }
}
// Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)

  

  1. java中 未显式定义构造函数的类,编译器会自动添加默认构造器,将所有存储属性初始化为默认值。
  2. 类的方法名也可以与类同名,因为方法有返回值,而构造函数的返回值是缺省的。
  3. 创建类的实例,可以不用构造方法:
    1. 比如调用对象的clone()方法,从内存上对已有对象的影印。
    2. 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法,是从文件中还原类的对象,也不会调用构造函数。
  4. java中没有析构函数,但提供了类似的finalize()方法。在回收类的对象时执行本方法。
  5. static, 静态变量的初始化如果需要计算,仅在第一次加载类时执行一次。
    1. 在类被加载时static修饰的成员字段被初始化,与类关联,只要类存在,static字段就存在。一个static字段单独划分一块存储空间,不与具体的对象绑定在一起,该存储空间被类的各个对象所共享。
    2. java中 静态变量和方法可以被实例对象调用(不推荐这样)

嵌套类, 内部类(非静态的嵌套类)

  1. 内部类中不能有静态成员
  2. 非静态方法,内部类里可以访问非静态字段,方法,也可以访问静态字段,方法,静态嵌套类
  3. 而静态方法,静态嵌套类里只能操作类中的静态元素,不能直接操作实例元素。因为非静态的方法,变量在实例化之前是不存在的
  4.  内部类实例化:MyClass.Nest2 nest = new MyClass().new Nest2();
  5.  同时静态类只能出现在内部,外部类不能使用static修饰符。

     

public class MyClass {
    int x = 1;
    static  int y = 2;
    void play(){
        System.out.println(x);
    }
    static  void play2(){
        //静态方法中只能操作静态的变量和方法
        //System.out.println(x);
        y = 3;
        System.out.println(y);
    }
    static class Nest1{
        void play(int x){
            //静态的嵌套类里也只能操作外部类的静态的变量和方法
            //System.out.println(x);
            System.out.println(x);
        }
    }

    class Nest2{
        //Illegal static declaration in inner class MyClass.Nest2
        //static String b = ""; 
        void play(Object x){
            System.out.println(x);
        }
    }
    public static   void main(String[] args) {
        Nest1 a = new Nest1();
        a.play(0);

        //non-static variable this cannot be referenced from a static context
        Nest2 b = new MyClass().new Nest2();
        b.play(0);
        
        new  MyClass2().play();
    }
}

class MyClass2 {
    MyClass.Nest2 n2;
    MyClass.Nest1 n1;

    void play(){
        // 静态嵌套类的实例化
        n1 = new MyClass.Nest1();
        n1.play(1);

        //内部类的实例化
        MyClass outer = new MyClass();
        n2 = outer.new Nest2();
        n2.play(n2);

        MyClass.Nest2 n3 = outer.new Nest2();
        n3.play(n3 );
        MyClass.Nest2 n4 = new MyClass().new Nest2();
        n4.play(n4);
    }
}

/*
0
0
1
MyClass$Nest2@659e0bfd
MyClass$Nest2@2a139a55
MyClass$Nest2@15db9742
*/

  

可变参数

 使用数组传递未知数量参数,需要手动将这些参数打包为数组,不仅繁琐,而且容易出错。所以有了可变参数的诞生,将封装数组的操作交给了编译器。

     void vaTest(int ... v){} // 与swift相比,省略号放在了前面。

   可变参数的方法存在模糊性(Ambiguous)

class test {
  void vaTest(int ... v){}
  void vaTest(boolean ... v){}
  void vaTest(int n, int ... v){}

   public static void main(String a[]){
       vaTest(1,2,3);
       vaTest(true);
       vaTest();  // Error,Ambiguous
       vaTest(1);// Error,Ambiguous
   }
}

 

继承

super 可以访问父类中被子类重写的属性和方法  super , this

    super.属性; //访问最近超类的属性

    super.方法   // 访问最近超类的方法 

    super();      //访问最近超类的构造函数

构造函数调用机制

在类层次中,从超类到子类按照继承的顺序调用构造函数。

     类A继承类B, 在实例化类A时,会先实例化类B,如果构造函数里有super(),则super()必须是子类构造函数中的第一条语句,而如果没有super(),那么也会先执行超类的默认构造函数或无参构造函数。 

class A{
	A(){
		System.out.println("init A()");
	}
}

class  B extends A{
	B(){
		System.out.println("init B()");
	}
	B(int x){
		System.out.println("init B(int x)");
	}
}

class C  extends B{
	C(){
		System.out.println("init C()");
	}
	
	C(int x){
		System.out.println("init C(int x)");
	}
	C(boolean x){
		super(2);
		System.out.println("init C(boolean x)");
	}
}

public class show2{
	public static void main(String args[]){
		C one = new C();
		/**
		 * init A()
		 * init B()
		 * init C()
		 */
		
		C two = new C(1);
		/**
		 * init A()
		 * init B()
		 * init C(int x)
		 */
		
		C three = new C(true);
		/**
		 * init A()
		 * init B(int x)
		 * init C(boolean x)
		 */
	}
}

  

方法重写

 java中可以直接重写超类的方法。

class A{
	void callme(){
		System.out.println("A's callme method");
	}
}

class  B extends A{
	void callme(){
		System.out.println("B's callme method");
	}
}

class C  extends B{
	void callme(){
		super.callme();
		System.out.println("C's callme method");
	}
}

public class show2{
	public static void main(String args[]){
		A a = new A();
		B b = new B();
		C c = new C();
		A r;
		
		r = a;
		r.callme();
		
		r = b;
		r.callme();
		
		r = c;
		r.callme();
	}
}

 

 

final

final 阻止变量修改

final 阻止方法重写

 1. 将方法声明为final ,有时可以提高性能。编译器可以自由地内联对这类方法的调用(当调用小的final方法时,编译器通常可以复制子例程的字节码,直接和调用方法的编译代码内联到一起。从而可以消除方法调用所需的开销。内联是final方法才有的选项。)。

   2 . 通常java在运行时动态分析对方法的调用,这称为后期绑定。而final 方法的调用却可以在编译时解析,这称为早期绑定

final 阻止继承

  抽象类本身是不完整的,需要子类提供完整的实现,所以不能同时将类声明为abstract 和 final

 

Object类

   java中所有其他类的超类,它的引用变量可以指向任何其他类的对象,包括数组。所有类的对象都可以使用Object类的方法。

     Object clone();   创建一个和将要复制的对象完全相同的新对象。

     boolean equals(Object objects); 判断一个对象是否和另一个对象相等。

     void finalize(); 在回首不再使用的对象之前使用

     final Class<?>getClass() 在运行时获取对象所属的类

     int hashCode() 返回与运行对象相关联的散列值

     final void notify()  恢复执行在调用对象上等待的某个线程

     final void notifyAll() 恢复执行在调用对象上等待的所有线程

     String toString() 返回一个描述对象的字符串

     final void wait()   等待另一个线程的执行

     final void wait(long milliseconds)

     final void wait(long milliseconds,int nanoseconds)

 

包 package

  包是多个类的容器,作用类似于命名空间。

  包是一种命名机制,也是一种可见性的控制机制,可以在包内定义包外部不能访问的类(不加访问修饰符)。

 

导入包:

  import java.util.date;

  import java.io.*;

 访问控制public ,private, protected,及默认(不加访问修饰符)

 

package p1;

public class Protection {
	int n = 1;
	private int n_pri = 2;
	protected int n_pro = 3;
	public int n_pub = 4;
	
	public Protection(){
		System.out.println("base constructor");
		System.out.println("n = " + n);
		System.out.println("n_pri = " + n_pri);
		System.out.println("n_pro = " + n_pro);
		System.out.println("n_pub = " + n_pub);
	}
}


package p1;

public class Derived extends Protection {
	Derived(){
		System.out.println("Derived constructor");
		System.out.println("n = " + n);
		// class only
		//System.out.println("n_pri = " + n_pri);
		System.out.println("n_pro = " + n_pro);
		System.out.println("n_pub = " + n_pub);
	}
}


package p1;

public class SamePackage {
	SamePackage(){
		Protection p = new Protection();
		
		System.out.println("SamePackage constructor");
		System.out.println("n = " + p.n);
		// class only
		//System.out.println("n_pri = " + p.n_pri);
		System.out.println("n_pro = " + p.n_pro);
		System.out.println("n_pub = " + p.n_pub);
	}
}


package p2;

import p1.Protection;

public class Protection2 extends Protection {
	Protection2(){
		System.out.println("Derived other package constructor");
		// class or package only
		//System.out.println("n = " + n);
		// class only
		//System.out.println("n_pri = " + n_pri);
		System.out.println("n_pro = " + n_pro);
		System.out.println("n_pub = " + n_pub);
	}
}


package p2;

public class otherPackage {
	otherPackage(){
		p1.Protection p = new p1.Protection();
		
		System.out.println("otherPackage constructor");
		// class or package only
		//System.out.println("n = " + p.n);
		// class only
		//System.out.println("n_pri = " + p.n_pri);
		// class,subclass or package only
		//System.out.println("n_pro = " + p.n_pro);
		System.out.println("n_pub = " + p.n_pub);
	}
}

 

 

接口 interface  

接口和类的区别:接口不能有实例变量,无法维护状态信息。

  1. 可声明为public 或 默认访问级别,也可以用abstract
  2. java将接口从其实现中完全抽象出来,接口与抽象类很像,但接口还有其他功能:一个类可以实现多个接口,但一个类只能继承一个超类。
  3. 接口是对事物行为、属性的更高级别的抽象,放入接口中的全部都是不可变更的东西。同时接口是公开的,里面不能有私有的方法或变量。
  4. 接口中没有实例变量,接口内的方法没有方法体。  
  5. 接口中可以声明变量,它们会被隐式地标识为 final 和 static。 实现接口的类不能修改它们。
  6. 接口中所有的变量和方法都被隐式地声明为 public。
  7. 如果在类实现的两个接口中都声明了同一个方法,则这两个接口的客户都将可以使用这个方法。
  8. 实现接口的方法必须被声明为 public。
  9. 如果类包含了一个接口,但并没有实现该接口定义的全部方法,那么必须将类声明为抽象类
interface CallBack{
	int x = 0;
	void  callback(int param);
}
abstract class Incomplete implements CallBack {
     int a,b;
     void show {
         System.out.println(a + "  " + b);
    }
    // ...
}

 接口扩展接口

interface A{
    void method1();
}

interface B extends A{
    void method2();
}

接口中的变量

// 类似C 中的 #define 常量或 const 声明
// 如果接口不包含方法,那么实现该接口就相当于把接口中的常量导入到类名称空间中

import java.util.Random;

interface ShareConstants{
    int NO = 0;
    int YES = 1;
    int MAYBE = 2;
    int LATER = 3;
    int SOON = 4;
    int NEVER = 5;
}

class Question implements ShareConstants{
    Random rand = new Random();
    int ask(){
        int  prob = (int) (100 * rand.nextDouble());
        if (prob < 30) {
            // 在实例方法中直接使用静态变量,即可以 this.NO,而非必需Question.NO
             return NO;  // 30%
        }
        else  if (prob < 60) {
             return YES;  // 30%
        }
        else  if (prob < 75) {
             return LATER;  // 15%
        }
        else  if (prob < 98) {
             return SOON;  // 13%
        }
        else  {
             return NEVER;  // 2%
        }
    }
}

class AskMe implements ShareConstants{
     static void answer(int result){
           switch(result){
               case NO:
                    System.out.println("No");
                    break;
               case YES:
                    System.out.println("Yes");
                    break;
               case MAYBE:
                    System.out.println("Maybe");
                    break;
               case LATER:
                    System.out.println("Later");
                    break;
               case SOON:
                    System.out.println("Soon");
                    break;
               case NEVER:
                    System.out.println("Never");
                    break;
           }
     }

      public static void main(String a[]){
            Question q = new Question ();
            answer(q.ask());
            answer(q.ask());
            answer(q.ask());
            answer(q.ask());
            answer(q.ask());
      }
}

 

 嵌套接口

将接口声明为某个类或另一个接口的成员。private,public, protected,或默认

// a nested interface example

class A{
	 //a nested interface
	public interface NestedIF{
		boolean isNotNegative(int x);
	}
}

class B implements A.NestedIF{
	public boolean isNotNegative(int x){
		return x < 0 ? false : true;
	}
}

class NestedDemo{
	public static void main(String args[]){
		A.NestedIF nif = new B();
		
		if (nif.isNotNegative(10))
			System.out.println("ssss");
	}
}

接口方法中添加默认实现(jdk 8 ),关键字default

   在jdk 8之前,接口只能定义“有什么”,而不能定义“如何实现”。

   从jdk 8开始,可以在接口方法中添加默认实现。然而,默认实现只是构成了一种特殊用途,接口最初的目的没有改变。

  接口添加默认实现的好处有:

    1.  提供了可选功能,接口方法 带有了默认实现,则实现该接口的类就不必在不需要该功能时提供占位符实现了。

    2.  可以优雅地随时间演变接口,当为一个广泛使用的接口添加一个新方法时,不必破环现有代码。

// 接口默认方法的定义类似于为类定义方法,区别在于,需带关键字default

public interface MyIF{
    int getNumber();

    default String getString(){
          return "Default String";
    }
}

 

默认实现的名称冲突

因为接口依然不能有实例变量。所以接口的特征没有改变,依然不能维护状态信息。

所以默认方法的引入,只是带来了额外的灵活性。并未有C++那样的多重继承。

 但类确实可以从接口中继承一些行为,在一定程度上支持多重继承,也就可能发生名称冲突。

 解决办法:

  1. 在所有情况下,类实现的优先级高于接口的默认实现。类中的重写将覆盖接口中的默认方法,即便几个接口发生名称冲突,也会一起被重写。

  2. 当类实现的两个接口提供了相同的默认方法,但是类没有重写该方法时,则会发生错误。

  3. 如果一个接口继承了另一个接口,并且两个接口定义了相同的默认方法。那么继承接口的版本具有更高优先级。

 

接口可以定义一个或多个静态方法(jdk 8)

  1. 接口定义的静态方法可以独立于任何对象调用
  2. 实现接口的类或子接口不会继承接口中的静态方法。
public interface MyIF{
    int getNumber();
    default String getString(){
         return "Default String ";
    }

    static int getDefaultNumber(){
         return 0;
    }
}

// 调用

int defNum =  MyIF.getDefaultNumber();

 

 

动态方法调度(运行时多态的基础)

使用超类或接口,依赖倒置,有利于解偶,但要在运行时动态查找方法,性能上会增加额为负担。

所以在性能要求苛刻的代码中,应当谨慎小心。

 

异常处理

 在不支持异常处理的语言中,必须手动检查和处理错误,而java的异常处理避免了这些问题,并且在处理过程中采用面向对象的方式管理运行时错误。

java异常是用来描述在一段代码中发生的异常情况的对象。当出现引起异常的情况时,就会创建用于表示异常的对象,并在引起错误的方法中抛出异常对象,方法可以选择自己处理异常,也可以继续传递异常,无论采用哪种方式,在某一点都会捕获并处理异常,异常可以由java运行时系统生成,也可以通过代码手动生成,前者与那些违反java语言规则或java执行环境的基础性错误有关,后者通常用于向方法的调用者报告某些错误条件。

 

5个关键字: try ,catch , throw ,finally ,和  throws 

 

所有异常都是内置类 Throwable的子类。

 紧跟Throwable之下的是两个子类,将异常分为两个不同的分支。

   Exception:既可以用于用户程序应当捕获的异常情况,也可以用于创建自定义的异常类型的子类。

         RuntimeException

   Error:定义了在常规环境下不希望由程序捕获的异常,由java运行时系统使用,以指示运行时环境本身出现了某种错误。如堆栈溢出。通常是为了响应灾难性的失败而创建。应用程序通常不处理这类异常。

Throwable 重写了 toString()方法,从而可以返回一个包含异常描述的字符串。

 

未捕获的异常

  如果程序没有捕获异常,当Java运行时系统检测到错误操作时,它会构造一个新的异常对象,然后抛出,这会导致程序终止执行。

因为异常一旦抛出,就必须要有一个异常处理程序捕获该异常,并立即进行处理。如果程序员没有提供任何自己的异常处理程序,该异常就会由Java运行时系统提供的默认处理程序捕获,默认处理程序会显示一个描述异常的字符串,输出异常发生点的堆栈踪迹并终止程序。堆栈轨迹会显示导致错误的方法的调用序列,可以精确定位导致错误发生的步骤序列,帮助程序员调试。

 

程序员自己处理异常 try ... catch

  1. 可以修复错误,2.阻止程序自动终止。

 大部分设计良好的catch子句,都应当能够分辨出异常情况,然后继续执行。

 

try-catch 语句由一个 try 块后跟一个或多个 catch 子句构成,这些子句指定不同的异常处理程序。引发异常时,运行时系统会查找处理此异常的 catch 语句。如果当前执行的方法不包含这样的 catch 块,则查看调用当前方法的方法,然后会遍历调用堆栈。如果找不到 catch 块,则 CLR 会向用户显示一条有关未处理异常的消息并停止执行程序。

 

使用多条catch语句时,异常子类必须位于所有超类之前。否则会编译错误 “Unreachable catch block”

public class test {
    public static void main(String args[]){
    	try{
    		try{
            	
            	
//            	int a = args.length;
//            	System.out.println("a = " + a);
//            	int b = 42 / a;
//            	System.out.println(b);
//            	
            	int c[] ={1};
            	c[42] = 99;
            	
            	throw new NullPointerException("demo");
            	
            }
            catch(ArithmeticException e){
            	System.out.println("Divide by 0:" + e);
            }
            catch(ArrayIndexOutOfBoundsException e){
            	System.out.println("Array index oob:"+ e);
            }
    		finally{
    			System.out.println("finally");
    		}
            System.out.println("after");
    	}
    	catch(Exception e){
    		System.out.println("Exception:"+ e);
    	}
  }
}

throws(java的检查型异常处理)

 如果方法可能引发自身不进行处理的异常,就必须指明这种行为,以便方法的调用者能够防备这些异常。 throws子句列出了方法可能抛出的异常类型。

除了Error和 RuntimeExceptin 及其子类类型,对于所有其他类型的异常都必需这样处理。

package throwsDemo;

public class ThrowsDemo {
	public static void main(String args[]){
		try {
			throwOne();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    static void throwOne() throws IllegalAccessException{
		System.out.println("Inside throwOne");
		throw new IllegalAccessException("demo");
	}
}

 在java.lang中,Java定义了一些异常类,这些异常类中最常用的是RuntimeException的子类。这些异常不需要包含在方法的throws列表中

异常含义
ArithmeticException算术错误,例如除0
ArrayIndexOutOfBoundsException数组索引越界
ArrayStoreExcepion使用不兼容的类型为数组元素赋值
ClassCastException无效转换
EnumConstantNotPresentException使用未定义的枚举值
IllegalArgumentException使用非法参数调用方法
IllegalMonitorStateException非法的监视操作,例如等待未锁定的线程
IllegalThreadStateException环境或应用程序处于不正确的状态
IndexOutOfBoundsException某些类型的索引越界
NegativeArraySizeException使用负数长度创建数组
NullPointerException非法使用空引用
NumberFormatException字符串到数值格式的无效转换
SecurityException违反安全性
StringIndexOutOfBounds字符串索引越界
TypeNotPresentException类型未定义
UnsupportedOperationException不支持的操作
ClassNotFoundException类未定义
CloneNotSupportedException试图复制没有实现Cloneable接口的对象
IllegalAccessException对类的访问被拒绝
InstantiationException试图实例化一个抽象类或接口
InterruptedException一个线程被另一个线程中断
NotSuchFieldException请求的域变量不存在
NotSuchMethodException请求的方法不存在
ReflectiveOperationExcepton与反射相关的异常的超类
  
  

 

public class ThrowsDemo {
	public static void main(String args[]){
		try{
		throwOne();
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
    static void throwOne(){
		System.out.println("Inside throwOne");
		throw new ClassCastException("demo");
	}
}

 

自定义异常

class MyException extends  Exception {
   private int detail;
   
   MyException(int a){
	   detail = a;
   }
   
   public String toString(){
	   return "MyException["+detail+"]";
   }
}

class ExceptionDemo{
	static void compute(int a) throws MyException{
		System.out.println("Called compute("+a+")");
		if (a>10){
			throw new MyException(a);
		}
		System.out.println("Normal exit");
	}
	
	public static void main(String args[]){
		try {
			compute(1);
			compute(20);
		} catch (MyException e) {
			// TODO Auto-generated catch block
			System.out.println("Caught: "+e);
		}
	}
}

 链式异常(jdk1.4)

 通过链式异常,可以为异常关联另一个异常。

   为了使用链式异常,Throwable 增加了两个构造函数和两个方法。

     为异常设置原因:

    Throwable(Throwable causeExc)

    Throwable(String msg, Throwable causeExc)

    Throwable initCause(Throwable causeExc)

     查询引发异常的原因:

    Throwable getCause()  // 返回引发当前异常的异常,如果没有则返回null 

public class ChainExcDemo {
	static void demoproc(){
		
		NullPointerException e = new NullPointerException("top layer");
		
		e.initCause(new ArithmeticException("cause"));
		
		throw e;
	}
	
	public static void main(String args[]){
		try{
			demoproc();
		}catch(NullPointerException e){
			System.out.println("Caught: " + e);
			System.out.println("Original cause: " + e.getCause());
		}
	}
}

 

 jdk 7 新增3个特性

带资源的try,当资源不再需要时会自动释放。

多重捕获,允许通过相同的catch子句捕获多个异常,每个多重捕获参数都被隐式声明为final

public class MultiCatch {
	public static void main(String args[]){
		int a = 10,b = 0;
		int vals[] = {1,2,3};
		
		try{
			int result = a / b;
			vals[10] =19;
			
		}
		catch(ArithmeticException|ArrayIndexOutOfBoundsException e){
			System.out.println("Exception Caught:" + e);
		}
		System.out.println("after");
	}
}

更精确地重新抛出 more precise rethrow(最后重新抛出 final rethrow)

 更精确地重新抛出 会对重新抛出的异常类型进行限制,只能重新抛出满足以下条件的经检查的异常:

    由关联的try代码块抛出,没有被前面的catch子句处理过,并且是参数的子类型或者超类型。 为了强制使用这一特性,catch参数须被有效地或者显式地声明为final

class FirstException extends Exception{
	FirstException(String s){
		super(s);
	}
}

class SecondException extends Exception{
	SecondException(String s){
		super(s);
	}
}

public class Rethrowing { 
	// f会抛出一个异常 
	public static void f(boolean a) throws FirstException, SecondException   { 
		 System.out.println("originating the exception in f()"); 
		 if(a){
			 throw new FirstException("thrown from f()"); 
		 }
		 else{
			 throw new SecondException("thrown from f()"); 
		 }
	} 
	
	// g中捕获f抛出的Exception异常并重新抛出
	
// 报错,更精确的异常抛出 catch子句中抛出的异常必须来自try代码块,否则编译器无法解析
// 这里 throws子句需改为 throws Exception,恢复为普通的重新抛出异常
//	public static void g() throws FirstException, SecondException { 
//		 try { 
//			 f(true); 
//		 } 
//		 catch(Exception e) { 	  
//		     System.out.println("Inside g(), e.printStackTrace()"); 
//		     
//		     // 如果e 被重新赋值为其他异常
//		     e= new FirstException("22");
//		     throw e; 
//		 }
//	}
	
	// 更精确的重新抛出
	// 即使 catch 子句的异常参数e的类型是 Exception,
	// 但 throws 子句中却可指定异常类型为  FirstException 和 SecondException。
	// Java SE 7编译器要求语句抛出的异常必须来自于 try 块,   
	// 并且 try 块抛出的异常只能是 FirstException 和 SecondException。
	public static void g()throws FirstException, SecondException{
		 try { 
			 f(true); 
		 } 
		 catch(final Exception e) { 	  
			 System.out.println("Inside g(), e.printStackTrace()"); 
			 throw e; 
		 }
	}
	
	public static void main(String[] args){ 
		try { 
			g(); 
		}
		catch(Exception e) { 
		    System.out.println("Caught in main, e.printStackTrace()"); 
		    e.printStackTrace(); 
		} 
	}
}

 

多线程

 java内置支持多线程。多线程是特殊形式的多任务处理

 多线程程序包含同时运行的多个部分,每个部分被称为一个线程,并且每个线程定义了一个单独的执行路径。

 多任务处理 有两种类型: 基于进程和基于线程。

   进程本身是程序,基于进程的多任务处理就是允许计算机同时运行多个程序的特性。程序时调度程序的最小代码单元。

   而基于线程的多任务环境中,最小的可调度代码单元是线程。这意味着单个程序可以同时执行多个任务。

 

Thread类 和 Runnable接口

Thread作为线程代理,定义了一些管理线程的方法:

 getName(),getPriority(), isAlive(), join() /*等待线程终止*/, run()/*线程的入口点*/, sleep()/*线程挂起*/, start()/*调用线程的run()方法启动线程*/

 

主线程: Thread.currentThread() (main/*默认名称*/,5/*优先级*/,main/*线程组*/)

    在java程序启动时,会立即开始运行的一个线程。

     其他子线程都是从主线程产生的。

   通常主线程必须是最后结束执行的线程,因为它要执行各种关闭操作。

public class CurrentThreadDemo {
	public static void  main(String args[]){
		Thread t = Thread.currentThread();
		System.out.println("Current thread: "+ t);
		
		t.setName("my thread");
		System.out.println("after name change: "+ t);
		
		try{
			for(int n= 5; n>0;n--){
				System.out.println(n);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("InterruptedException:"+ e);
		}
	}
}

 

实现Runnable接口创建线程

  只需实现run方法,就像main线程一样,区别在于run方法为程序中另外一个并发线程的执行建立了一个入口点,当run方法返回时,这个线程将结束。

class NewThread implements Runnable {
	private Thread t;
	private String name;
	
	NewThread(String threadName){
		name = threadName;
		t = new Thread(this,threadName);
		System.out.println("Child thread:"+ t);
		t.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try{
			for(int i =5; i>0;i--){
				System.out.println("Child thread "+name+":"+ i);
				Thread.sleep(500);
			}
		}
		catch(InterruptedException e){
			System.out.println("Child  "+name+"interrupted:"+ e);
		}
		System.out.println("Exiting child  "+name+"thread");
	}
}

class RunnableDemo {
	public static void main(String args[]){
		// 开启子线程
		new NewThread("a");
		new NewThread("b");
		new NewThread("c");
		
		try{
			for(int i=5;i>0;i--){
				System.out.println("Main thread:"+ i);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("Main interrupted:"+ e);
		}
		System.out.println("Exiting Main thread");
	}
	
}

 

 主线程必须在最后结束运行,因为对于某些旧的JVM,如果主线程在子线程完成之前结束,java运行时系统可能会挂起。

 

扩展Thread类 创建线程

class NewThread extends Thread{
	
	NewThread(){
		super("Demo Thread");
		System.out.println("Child Thread:"+this);
		start();
	}
	
	public void run(){
		try{
			for(int i =5; i>0;i--){
				System.out.println("Child thread:"+ i);
				Thread.sleep(500);
			}
		}
		catch(InterruptedException e){
			System.out.println("Child interrupted:"+ e);
		}
		System.out.println("Exiting child thread");
	}
}

public class EntendThread {
	public static void main(String args[]){
		// 开启子线程
		new NewThread();
		
		try{
			for(int i=5;i>0;i--){
				System.out.println("Main thread:"+ i);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("Main interrupted:"+ e);
		}
		System.out.println("Exiting Main thread");
	}
}

join()

在主线程中执行子线程A.join(),则主线程会更这个子线程A执行完毕之后才会进行后续操作

class NewThread implements Runnable {
	Thread t;
	private String name;
	
	NewThread(String threadName){
		name = threadName;
		t = new Thread(this,threadName);
		System.out.println("Child thread:"+ t);
		t.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try{
			for(int i =5; i>0;i--){
				System.out.println("Child thread "+name+":"+ i);
				Thread.sleep(500);
			}
		}
		catch(InterruptedException e){
			System.out.println("Child  "+name+"interrupted:"+ e);
		}
		System.out.println("Exiting child  "+name+"thread");
	}
}

class RunnableDemo {
	public static void main(String args[]){
		// 开启子线程
		NewThread A = new NewThread("a");
		NewThread B = new NewThread("b");
		NewThread C = new NewThread("c");
		
		System.out.println("thread a is alive:"+ A.t.isAlive());
		System.out.println("thread b is alive:"+ B.t.isAlive());
		System.out.println("thread c is alive:"+ C.t.isAlive());
		
		try{
			System.out.println("waiting for threads to finish");
			A.t.join();
			B.t.join();
			C.t.join();
			
			for(int i=5;i>0;i--){
				System.out.println("Main thread:"+ i);
				Thread.sleep(1000);
			}
		}
		catch(InterruptedException e){
			System.out.println("Main interrupted:"+ e);
		}
		
		System.out.println("thread a is alive:"+ A.t.isAlive());
		System.out.println("thread b is alive:"+ B.t.isAlive());
		System.out.println("thread c is alive:"+ C.t.isAlive());
		
		System.out.println("Exiting Main thread");
	}
	
}

同步synchronized

synchronized方法
class Callme{
	synchronized void call(String msg){
		System.out.print("["+msg);
		try{
			Thread.sleep(1000);
		}
		catch(InterruptedException e){
			System.out.println("InterruptedException");
		}
		System.out.println("]");
	}
}

class Caller implements Runnable{
	String msg;
	Callme target;
	Thread t;
	
	public Caller(Callme targ,String s){
		target= targ;
		msg =s;
		t = new Thread(this);
		t.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		target.call(msg);
	}
	
}

public class Synchronized {
	public static void main(String args[]){
		Callme target = new Callme();
		Caller ob1 = new Caller(target,"hello");
		Caller ob2 = new Caller(target,"Synchronized");
		Caller ob3 = new Caller(target,"world");
		
		try{
			ob1.t.join();
			ob2.t.join();
			ob3.t.join();
			
		}
		catch(InterruptedException e){
			System.out.println("InterruptedException");
		}
	}
}
synchronized 语句
class Callme{
	 void call(String msg){
		System.out.print("["+msg);
		try{
			Thread.sleep(1000);
		}
		catch(InterruptedException e){
			System.out.println("InterruptedException");
		}
		System.out.println("]");
	}
}

class Caller implements Runnable{
	String msg;
	Callme target;
	Thread t;
	
	public Caller(Callme targ,String s){
		target= targ;
		msg =s;
		t = new Thread(this);
		t.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized(target){
			target.call(msg);
		}
	}	
}

public class Synchronized {
	public static void main(String args[]){
		Callme target = new Callme();
		Caller ob1 = new Caller(target,"hello");
		Caller ob2 = new Caller(target,"Synchronized");
		Caller ob3 = new Caller(target,"world");
		
		try{
			ob1.t.join();
			ob2.t.join();
			ob3.t.join();
			
		}
		catch(InterruptedException e){
			System.out.println("InterruptedException");
		}
	}
}

进程间通信机制:wait(),notify()及notifyAll()

java通过wait(),notify()及notifyAll() 提供了一种进程间通信机制。这三个方法只能在同步上下文中调用。

    wait() 方法通知调用线程放弃监视器并进入休眠。直到其他一些线程进入同一个监视器并调用notify()方法或notifyAll()方法。

    notify()方法唤醒调用相同对象的wait()中的线程。

    notifyAll() 方法唤醒调用相同对象的wait()中的所有线程,其中一个线程将得到访问授权。

    wait()方法有另一种形式,可以指定等待的时间间隔。因为线程有极小可能被假唤醒(没有调用notify,而线程被恢复),   所以应当在一个检查线程等待条件的循环中调用wait()

// 队列
class Q{
	int n;
	boolean valueSet = false;
	
	synchronized int get(){
		while(!valueSet){
			try{
				wait();
				
			}
			catch(InterruptedException e){
				System.out.println("InterruptedException");
			}
		}
		System.out.println("Got: "+ n);
		valueSet =false;
		notify();
		return n;
	}
	
	synchronized void put(int n){
		while(valueSet){
			try{
				wait();
				
			}
			catch(InterruptedException e){
				System.out.println("InterruptedException");
			}
		}
		this.n =n ;
		valueSet =true;
		System.out.println("Put: "+ n);
		notify();
	}
}

class Producter implements Runnable{
	Q q;
	
	Producter(Q q){
		this.q = q;
		new Thread(this,"Producter").start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		int i = 0;
		while(i < 100){
			q.put(i++);
		}
	}
}


class Consumer implements Runnable{
	Q q;
	
	Consumer(Q q){
		this.q = q;
		new Thread(this,"Consumer").start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(q.get() < 99){
		}
	}
}
public class Wait2Notify {
	public static void main(String args[]){
		Q q = new Q();
		new Producter(q);
		new Consumer(q);
	}
}

死锁

 一个线程进入对象X的监视器,另一个线程进入对象Y的监视器,如果X中的线程试图调用对象Y的任何同步方法,那么都会被阻塞,需要等待当前占据对象Y的线程执行完毕,移出对象Y的监视器,而如果对象Y中的线程也试图调用对象X的任何同步方法,则会造成死锁。

class A{
	synchronized  void foo(B b){
		String name = Thread.currentThread().getName();
		System.out.println(name + " entered A.foo()");
		
		try{
			Thread.sleep(1000);
			
		}
		catch(Exception e){
			System.out.println("A Interrupted");
		}
		
		System.out.println(name +" trying to call B.last()");
		b.last();
	}
	
	synchronized void last(){
		System.out.println("Inside A.last()");
	}
}
class B{
	synchronized void bar(A a){
		String name = Thread.currentThread().getName();
		System.out.println(name + " entered B.bar()");
		
		try{
			Thread.sleep(1000);
			
		}
		catch(Exception e){
			System.out.println("B Interrupted");
		}
		
		System.out.println(name +" trying to call A.last()");
		a.last();
	}
	
	synchronized void last(){
		System.out.println("Inside B.last()");
	}
}
public class DeadLock implements Runnable {
	A a = new A();
	B b = new B();
	
	DeadLock(){
		Thread.currentThread().setName("MainThread");
		Thread t = new Thread(this,"RacingThread");
		t.start();
		
		a.foo(b);
		System.out.println("back in main thread");
	}
	
	public  void run(){
		b.bar(a);
		System.out.println("back in other thread");
	}
	
	public static void main(String args[]){
		new DeadLock();
	}
}

挂起,恢复,停止

java 2以前,程序使用Thread类定义的suspend(),resume(),stop()方法。这些方法在java2不再使用的原因是:

  suspend()方法有时会导致严重的系统故障,假定线程为关键数据结构加锁,如果这是线程被挂起,那么这些锁将无法释放。其他可能等待这些资源的线程会被死锁。

  resume()与suspend()是配对使用的,所以也一起废弃。

  stop()方法有时也会造成严重的系统故障,假定线程正在向关键的重要数据结构中写入数据,并且只完成了部分发生变化的数据。如果这时停止线程,那么数据就够可能会处于损坏状态,问题是stop()会导致释放调用线程的所有锁,因此,另一个正在等待相同锁的线程可能会使用这些已损坏的数据。

所以现在面向函数编程开始流行,就是因为函数式编程不需要保存状态,也就不需要锁定,也就没有上述的各种状况。可以大大简化多线程操作的难度。

 

  现在,线程被设计为run()方法周期性进行检查,以确保是否应当挂起,恢复或停止线程自身的执行。

class NewThread implements Runnable{
	String name;
	Thread t;
	boolean suspendFlag;	
	
	NewThread(String threadName){
		name = threadName;
		t = new Thread(this,name);
		System.out.println("New Thread: "+ t);
		suspendFlag = false;
		t.start();
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try{
			for(int i = 15; i>0;i--){
				System.out.println(name +": "+ i);
				Thread.sleep(2000);
				synchronized(this){
					while(suspendFlag){
						wait();
					}
				}
			}
		}
		catch(InterruptedException e){
			System.out.println(name +" InterruptedException");
		}
		
		System.out.println(name +" exiting");
	}
	
	synchronized void mysuspend(){
		suspendFlag =true;
	}
	synchronized void myresume(){
		suspendFlag =false;
		notify();
	}
}

public class Mysuspend {
	public static void main(String args[]){
		NewThread ob1 = new NewThread("one");
		NewThread ob2 = new NewThread("two");
		
		try{
			Thread.sleep(1000);
			ob1.mysuspend();
			System.out.println("Suspending thread one");
			Thread.sleep(1000);
			ob1.myresume();
			System.out.println("Resuming thread one");
			
			ob2.mysuspend();
			System.out.println("Suspending thread two");
			Thread.sleep(1000);
			ob2.myresume();
			System.out.println("Resuming thread two");
		}
		catch(InterruptedException e){
			System.out.println("Main thread InterruptedException");
		}
		
		try{
			System.out.println("Waiting for threads to finish");
			ob1.t.join();
			ob2.t.join();
		}
		catch(InterruptedException e){
			System.out.println("Main thread InterruptedException");
		}
		
		System.out.println("Main thread exiting");
	}
}

 线程状态: if(t.getState()  == Thread.State.RUNNABLE)

 BLOCKED/*因为正在等待需要的锁儿挂起执行*/,

 NEW/*线程换没有开始执行*/,

 RUNNABLE/*线程要么当前正在运行,要么在获取cpu的访问权后执行*/,

 TERMINATED/*线程已经完成执行*/,

 TIMED_WAITING/*线程挂起执行一段指定的时间,如sleep(),暂停版的wait(),join()*/,

 WAITING/*线程因为某些动作而挂起执行,如调用非暂停版的wait(),join()*/

   

线程的上下文切换需要一定的开销,如果创建的线程太多,可能反而会降低程序的性能。 Fork/Join 框架创建可自动伸缩的计算密集型应用程序

 

Android中的Handler

/**
 * 执行批量访问
 *
 * @param token access_token
 */
private void doRequestCurrent(final String token) {
    for (UrlRequestBean bean : requestData) {
        if (!bean.isCanel && !bean.isBegin) {
            bean.isBegin = true;
            doRequest(bean, token);
        }
    }
    // 移除已取消的bean
    Iterator<UrlRequestBean> iterator = requestData.iterator();
    while (iterator.hasNext()) {
        UrlRequestBean bean = iterator.next();
        if (bean.isCanel) {
            iterator.remove();
        }
    }
}
/**
 * 访问接口,不会自动获取token
 *
 * @param urlBean UrlRequestBean
 */
private void doRequest(final UrlRequestBean urlBean, final String token) {
    if (!urlBean.isCanel) {
        urlBean.getBlocks().beforeRequest();
        if (token != null) {
            final Handler handler = new MyHandle(urlBean, false);
            HttpPostThread httpPostThread = new HttpPostThread(handler, urlBean, token);
            new Thread(httpPostThread).start();
        }
    }
}


/**
 * handler实现
 */
static private class MyHandle extends Handler {
    private WeakReference<UrlRequestBean> urlBean_weak;
    private boolean isTokenRequest = false;

    MyHandle(UrlRequestBean urlBean, boolean value) {
        this.urlBean_weak = new WeakReference<>(urlBean);
        isTokenRequest = value;
    }

    public void handleMessage(Message msg) {
        final UrlRequestBean urlBean = urlBean_weak.get();
        if (urlBean.getContext() != null || isTokenRequest) {
            switch (msg.what) {
                case 200:
                    // 获取网络成功
                    Bundle data = msg.getData();
                    String s = data.getString("value");
                    // 返回信息输出
                    LogContent.printLog(s);

                    if (!urlBean.isCanel && s != null) {
                        try {
                            JSONObject jsonObject = new JSONObject(s);
                            final Activity context = MyApplication.getTopActivity();
                            final DialogDiy2 dd = ((ActivityBase)context).dialogDiy2;
                            final CanGoToLoginActivity canGoToLoginActivity = new CanGoToLoginActivity();
                            final boolean goLogin = canGoToLoginActivity.isGoToLoginActivity(jsonObject);
                            if (goLogin) {
                                if (!dd.build.isShowing()) {
                                    Log.d("test", String.valueOf(dd.build.isShowing()));
                                    dd.showNormalDialog("您的账号在其它终端登录!", null, null, null, new DialogDiy2.MyDialogOnClickListener() {
                                        @Override
                                        public void onClick(View v) {
                                            // 返回登陆页
                                            urlBean.getBlocks().beforeGOlogin();
                                            canGoToLoginActivity.goToLoginActivity(context);
                                        }
                                    });
                                }
                            } else {
                                // 解析数据
                                urlBean.getBlocks().onGetData(jsonObject);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            urlBean.getBlocks().onError();
                        }
                    }
                    break;
                default:
                    LogContent.printLog(msg.what + ":handler.default");
                    if (!urlBean.isCanel) {
                        urlBean.getBlocks().onError();
                    }
                    break;
            }
        }
        // 移除已完成的访问。
        UrlRequestManager requestManager = UrlRequestManager.Instance;
        requestManager.removeRequest(urlBean);
        requestManager.isRefreshing = false;
    }
}

/**
 * 异步线程
 */
private class HttpPostThread implements Runnable {
    /**
     * handler处理
     */
    final private Handler handler;
    final private UrlRequestBean urlBean;
    final private String token;

    public HttpPostThread(Handler handler, UrlRequestBean urlBean, String token) {
        this.handler = handler;
        this.urlBean = urlBean;
        this.token = token;
    }

    @Override
    public void run() {
        // 获取我们回调主ui的message
        String url = urlBean.getUrl();
        try {
            HttpPost httpRequest = new HttpPost(url);

            List<BasicNameValuePair> postValue = urlBean.getPostValue();
            if (token != null) {
                postValue.add(new BasicNameValuePair("access_token", token));
            }

            httpRequest.setEntity(new UrlEncodedFormEntity(postValue, HTTP.UTF_8));

            HttpClient client = SSLSocketFactoryEx.getNewHttpClient();
            // 请求超时
            client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
            // 读取超时
            client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
            HttpResponse response = client.execute(httpRequest);
            Log.d("test","begin");
            int resultCode = response.getStatusLine().getStatusCode();
            if (resultCode == 200) {
                // 获得数据
                String str = EntityUtils.toString(response.getEntity());
                Message msg = new Message();
                msg.what = resultCode;
                Bundle data = new Bundle();
                data.putString("value", str);
                msg.setData(data);
                handler.sendMessage(msg);
            } else {
                // 错误
                Message msg = new Message();
                msg.what = resultCode;
                handler.sendMessage(msg);
            }
        } catch (Exception e) {
            // 超时 or数据解析出错
            e.printStackTrace();
            Message msg = new Message();
            msg.what = -1;
            handler.sendMessage(msg);
        }
    }
}

  

枚举(jdk 5

 从jdk 5.0开始枚举 被添加到java语言中, 不同的是,java的枚举是用类实现的。所以可以具有构造函数,方法及实例变量,甚至实现接口。

enum Apple{
	//枚举常量 被隐式声明为Apple的 public static final 成员,其类型声明为枚举的类型。
	Jonathan,GoldenDel,RedDel,Winesap,Cortland
}
public class EnumDemo {
	Apple ap = Apple.Cortland;
	
	// 比较相等性用 ==
	boolean test(Apple a){
		// 会显示名称 Jonathan
		System.out.println(a);
		
		return a == ap;
	}
	
	void switchTest(){		
		switch(ap){
		case Jonathan:
			// ...
		case GoldenDel:
			// ...
			
		default:
			// ...
		}
	}
}

 所有枚举自动包含两个预定义方法 values() 和 valueOf()

enum Apple{
	//枚举常量 被隐式声明为Apple的 public static final 成员,其类型声明为枚举的类型。
	Jonathan,GoldenDel,RedDel,Winesap,Cortland
}
public class EnumDemo {
	public static void main(String args[]){
		Apple ap;
		
		System.out.println("Here are all Apple constants");
		
		Apple allApples[] = Apple.values();
		for(Apple a : allApples){
			System.out.println(a);
		}
		
		ap = Apple.valueOf("GoldenDel");
		System.out.println("ap contains " + ap);
	}
}

 

// java枚举的类特性
enum Apple{
	// 实例对象
	Jonathan(10),GoldenDel(9),RedDel,Winesap(15),Cortland(8);
	
	// 变量
	private int price;
	
	// 构造函数
	Apple(int p){
		price = p;
	}
	
	Apple(){
		price = -1;
	}
	// 方法
	int getPrice(){
		return price;
	}
}

class EnumDemo{
	public static void main(String args[]){
		Apple ap =  Apple.Winesap;
		System.out.println("Winesap costs "+ ap.getPrice() + " cents.\n");
		
		System.out.println("All apple prices");
		for (Apple a : Apple.values()){
			
			if (a.compareTo(ap) < 0){
				System.out.println(a.ordinal() +" : " +a+" costs "+ a.getPrice()+ " cents."+ a + " before "+ ap);
			}
			else if (a.compareTo(ap) > 0){
				System.out.println(a.ordinal() +" : " +a+" costs "+ a.getPrice()+ " cents."+ a + " after "+ ap);
			}
			else {
				System.out.println(a.ordinal() +" : " +a+" costs "+ a.getPrice()+ " cents."+ a + " equal "+ ap);
			}
		}
	}
}

 

 枚举不能继承其他类,因为所有枚举都自动继承超类 java.lang.Enum, 虽然同样具有面向对象的特性,但java的枚举与swift差别很大。

 ordinal() 可以获取枚举常量在常量列表里的位置的值(序数值 0,1,2 ...)

 compareTo 可以比较相同类型的两个枚举常量的序数值。

 equals() 方法 等同 ==

测试

public class MyClass {
    enum type{
        A,B, MyClass3, C
    }
    enum type2{
        A(3),B(4),C(7);
        int index;
        type2(int index){
            this.index = index;
        }
        void print(){
            System.out.println(index);
            // 枚举中也不能调用外部类的实例变量
            //System.out.println(x);
        }
    }
    public static   void main(String[] args) {
        new  MyClass2();
        System.out.println(type.C.ordinal());
    }
}

public enum MyClass3{
    A,C,B
}

public class MyClass2 {
    MyClass2(){
        // 定义在外部的枚举,枚举值相当于几个静态常量
        System.out.println(MyClass3.A);
        System.out.println(MyClass3.C.ordinal());
        // 枚举不能实例化
        //MyClass3 D = new MyClass3();

        // 定义在类内部的枚举
        System.out.println(MyClass.type.C.ordinal());
        System.out.println(MyClass.type2.C);
        MyClass.type2.C.print();
        // 枚举不能实例化
        // MyClass.type2 D = new MyClass.type2(8);
    }
}

// 输出
//        A
//        1
//        3
//        C
//        7
//        3

 

转载于:https://www.cnblogs.com/wj033/p/4585395.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值