zoukankan      html  css  js  c++  java
  • 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修饰符。
    6.  局部内部类: 直接在方法中定义的类,java中特有的闭包实现形式

         

    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.
    ");
    		
    		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
  • 相关阅读:
    项目管理5大过程9大知识域44个定义
    linux centos6.5 修改ip地址
    .Net 6 已知问题集
    第二次阅读作业——程志
    采访大四学长整理笔记
    c#
    团队作业三两感想 by 程志
    搞定3G上网
    高焕堂Android應用框架原理與程式設計代码补遗(一)
    要素类属性内容全角换半角
  • 原文地址:https://www.cnblogs.com/wj033/p/4585395.html
Copyright © 2011-2022 走看看