【笔记】Java从入门到精通 | 核心篇
Java核心篇是Java语言学习的重点,需要充分理解面向对象的思想。入门阶段要达到的要求是会“用”,就是能用Java编写代码实现需求所要的基本功能,之后随着对Java编程思想的学习深入,慢慢理解为什么要这么写,或者说应该怎么写。
一、类的继承和多态
继承和多态是面向对象语言中非常重要的特性,使用得当的话,会使整个程序的架构变得非常有弹性,减少冗余度。在开发的过程中,要多思考如何设计才能使得达到这个要求。
- 子类继承父类的构造方法,非private成员变量和方法,同时可以定义自己的变量,以及重写方法(包括构造方法),重写时方法修饰权限只能向范围大变化;
- 实例化子类对象时,子类构造方法会自动调用父类无参构造方法,先实例化父类对象,再实例化子类对象,有参构造方法不能被自动调用;
- 区别重写和重载:重写override,只有实现内容不同,体现的是父与子之间的多态性;重载overload,体现的是类的多态性,可以是参数类型/顺序/个数不同;
- 向上转型一般没问题,平行四边形也是四边形;向下转型须得用显示类型转化,不能说四边形是平行四边形,但可以定义一个“平行四边形”的四边形;
- 在父类的方法draw()中将子类对象作为参数(利用向上转型),根据不同子类对象实现不同的逻辑,可避免每个子类单独重写draw()方法,解决代码冗余问题,也易于维护,这是多态的一个应用;
- 顶层父类往往定义成抽象类(例如:图形类,并无明确的几条边,几个顶点,可能有抽象的方法——绘图,面积等),继承该类的子类必须重写其中的抽象方法;
- 未必每个子类都心甘情愿重写抽象父类的某个抽象方法,可以考虑放在接口中,实现该接口的类(必须)重写该方法,因为类不能同时继承多个父类,但是可以实现多个接口。
/**********继承/多态**********/ package com.kplayer.graph; //抽象类-图形类 public abstract class Graph { abstract void init(); //提供一个抽象init()方法,继承该抽象类的需重写 } //接口-计算面积 //类不能同时继承多个父类,但可实现多个接口 public interface Area { public void area(); //提供一个area()接口,实现该接口的需重写 } //父类-四边形类 public class Quadrangle extends Graph implements Area{ public double area; //成员变量:面积 public static void draw(Quadrangle q){ //成员方法:绘图 if(q instanceof Parallelogram){ System.out.println("Draw image of Parallelogram!"); }else if(q instanceof Square){ System.out.println("Draw image of Square!"); }else{ System.out.println("Draw image of Quadrangle!"); } } public void init(){ //继承抽象类,需重写init()方法 System.out.println("Initialize Quadrangle..."); } public void area(){ //实现接口,需重写area()方法 System.out.println("Compute area of Quadrangle!"); } public Quadrangle(){ //构造方法 System.out.println("Construct Quadrangle Success!"); } } //子类-平行四边形 public class Parallelogram extends Quadrangle{ public double width; //子类新增成员变量:长 public double height; //子类新增成员变量:高 public double angle; //子类新增成员变量:角 public double area; //子类新增成员变量:面积 public void area(){ System.out.println("Overloading method area!"); this.area = this.width*this.height; } //重写(重构:只方法实现内容不同),父与子之间的多态性,权限修正只能变大 public void init(){ System.out.println("Initialize Parallelogram(Overriding)..."); } //重载,类中多态性,参数类型/顺序/个数不同 public void area(double w, double h){ System.out.println("Overloading method area!"); this.area = w*h; } public Parallelogram(){ //无参构造函数 System.out.println("Construct Parallelogram Success!"); } public Parallelogram(double w, double h, double a){ //有参构造函数 this.width = w; this.height = h; this.angle = a; System.out.println("Construct Parallelogram Success!"); } public static void main(String[] args) { //实例化子类对象,自动调用父类无参构造函数,父类有参构造函数需用super() Parallelogram p = new Parallelogram(4,5,30); //Construct Quadrangle Success! //Construct Parallelogram Success! p.area(4,5); //Overloading method area! System.out.println("area of p = " + p.area); //area of p = 20.0 //向上转型,将子类对象(平行四边形)看作父类对象(四边形) Quadrangle.draw(p); //调用父类方法,多态的应用 //Draw image of Parallelogram! //向下转型,必须显式转换 Quadrangle q = new Parallelogram(); //Construct Quadrangle Success! //Construct Parallelogram Success! Parallelogram p2 = (Parallelogram) q; if(p2 instanceof Parallelogram){ System.out.println("q is Parallelogram!"); //q is Parallelogram! } } } //子类-正方形 public class Square extends Quadrangle { public double length; //子类新增成员变量:边长 public double area; //子类新增成员变量:面积 //计算面积 public void area(){ this.area = this.length*this.length; } public void area(double l){ this.area = l*l; } public Square(){ //无参构造函数 System.out.println("Construct Square Success!"); } public Square(double length){ //有参构造函数 this.length = length; System.out.println("Construct Square Success!"); } }
二、类高级特性
类中配合包与权限修饰符使用,可以控制他人对类成员的访问。
- Final变量必须在声明时赋值,设定后不能再改变。但这并不意味着恒定不变,要看该变量是装载时初始化,还是实例化对象时初始化,所以通常全局变量使用public static final修饰;
- Final方法不能被重写(private final方法似乎可以);
- Final类不能被继承,如果一个类被设置为final,则类中所有方法隐式设置为final形式。
更为有效的隐藏实现细节的技巧是使用内部类,可以向上转型为被内部类实现的公共接口。
- 内部类的对象实例化必须在外部类或外部类的非静态方法中实现:outclass.new innerClass() / public innerClass doit();其实内部类地位就和成员变量/方法差不多;
- 内部类向上转型为接口:a) 定义一个内部类,实现OutInterface接口,权限符为private,只有OuterClass可以访问;b) 定义一个方法,返回值类型为OutInterface接口,权限符为public,其它类都可以访问;c) 子类不能继承InnerClass,也不能访问f()方法,隐藏了实现细节。但是可以访问doit()方法,返回OutInterface接口,通过返回的接口可以访问InnerClass的f()方法。
/**********Final**********/ //Final变量 package com.kplayer.finals; import java.util.Random; import static java.lang.System.out; public class KPFinalV { //final类,不能被继承,所有方法隐式设置为final private static Random rand = new Random(); // 实例化一个Random类对象 private final int a1 = rand.nextInt(10); //产生0~10之间随机数 private static final int a2 = rand.nextInt(10); //产生0~10之间随机数 public static void main(String[] args) { KPFinalV fdata = new KPFinalV(); // 实例化一个对象 out.println("a1:" + fdata.a1); //0 out.println("a2:" + fdata.a2); //3 KPFinalV fdata2 = new KPFinalV(); // 实例化另外一个对象 out.println("重新实例化后a1:" + fdata2.a1); //1,每次实例化重新赋值 out.println("重新实例化后a2:" + fdata2.a2); //3,装载时初始化 } } //Final方法/类 package com.kplayer.finals; class KPFinalMpar { private final void doit() { //可以被重写 System.out.println("Parent.doit()"); } final void doit2() { //不能被重写 System.out.println("Parent.doit2()"); } public void doit3() { System.out.println("Parent.doit3()"); } } final class KPFinalMsub extends KPFinalMpar{ //不能被继承,所有方法隐式设为final形式 public final void doit() { //override System.out.println("Sub.doit()"); } // final void doit2(){ //Cannot override the final method from KPFinalMpar // System.out.println("Sub.doit2()"); // } public void doit3() { System.out.println("Sub.doit3()"); } } public class KPFinalM { public static void main(String[] args) { KPFinalMsub s = new KPFinalMsub(); s.doit(); //Sub.doit() KPFinalMpar p = s; //向上转型 // p.doit(); //The method doit() from the type KPFinalMpar is not visible p.doit2(); //Parent.doit2() p.doit3(); //Sub.doit3() } }
/**********内部类**********/ //成员内部类 package com.kplayer.innerclass; public class KPOuterClass { //内部类 class innerClass { int num = 5; //内部类成员变量 public void inf(int num) { //内部类成员方法 num++; //形参 this.num++; //内部类变量num KPOuterClass.this.num++; //外部类变量num } innerClass() { // 内部类构造方法 } } int num; //外部类成员变量 innerClass in = new innerClass(); // 在外部类实例化内部类对象引用 public void ouf() { in.inf(num); // 在外部类方法中调用内部类方法 } public innerClass doit() { // 外部类方法,返回值为内部类引用 // num=4; //外部类不可以直接访问内部类成员变量 in.num = 4; return new innerClass(); // 返回内部类引用 } public static void main(String args[]) { KPOuterClass out = new KPOuterClass(); // 内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现 KPOuterClass.innerClass in = out.doit(); KPOuterClass.innerClass in2 = out.new innerClass(); } } //内部类向上转型为接口 package com.kplayer.innerclass; interface OutInterface { //定义一个接口 public void f(); } class OuterClass { //定义一个内部类,实现OutInterface接口 //权限符为private,只有OuterClass可以访问 private class InnerClass implements OutInterface { InnerClass(String s) { //内部类构造方法 System.out.println(s); } public void f() { // 实现接口中的f方法 System.out.println("访问内部类中的f()方法"); } } //定义一个方法,返回值类型为OutInterface接口 //权限符为public,其它类都可以访问 public OutInterface doit() { return new InnerClass("访问内部类构造方法"); } } class OuterClassSub extends OuterClass{ //不能继承InnerClass,也不能访问f()方法,隐藏了实现细节 //可以访问doit()方法,返回OutInterface接口(向上转型) //通过返回的接口可以访问InnerClass的f()方法,却看不到细节 //编写子类的人员只有一个接口和外部类 } public class KPInterfaceInner { public static void main(String args[]) { OuterClassSub outsub = new OuterClassSub(); //实例化子类对象 OutInterface outinter = outsub.doit();//调用doit()方法,返回OutInterface接口 outinter.f(); //通过返回的接口可以访问InnerClass的f()方法 } } //局部内部类 package com.kplayer.innerclass; interface OutInterface2 { // 定义一个接口 } class KPOuterClass2 { //成员方法doit() public OutInterface2 doit(final String x) { //参数为final类型 //在方法中定义一个内部类 class InnerClass2 implements OutInterface2 { InnerClass2(String s) { s = x; System.out.println(s); } } return new InnerClass2("doit"); } public static void main(String args[]) { KPOuterClass2 out2 = new KPOuterClass2(); //实例化对象 OutInterface2 outi = out2.doit("访问内部类"); } } //匿名内部类 package com.kplayer.innerclass; interface OutInterface3 { //定义一个接口 } class KPOuterClass3{ //成员方法doit() public OutInterface3 doit(final String s){ return new OutInterface3(){ //声明匿名内部类 private int i=0; public int getValue(){ System.out.println(s); return i; } public void f(){ System.out.println("f()"); } }; } } //静态内部类 package com.kplayer.innerclass; public class KPOuterClass4 { int x=100; static class Inner{ //静态内部类 void doitInner(){ //System.out.println("外部类"+x); } public static void main(String args[]){ System.out.println("a"); } } }
三、集合类
Java提供了不同的集合类,具有不同的存储对象的方式,需掌握对集合进行遍历、添加、删除以及查找制定的对象。
/**********集合类**********/ package com.kplayer.collection; import java.util.*; public class KPCollection implements Comparable<Object>{ /*For Set Begin*/ String name; long id; public KPCollection(String name, long id) { //构造方法 this.id = id; this.name = name; } public int compareTo(Object o) { //重写接口方法 KPCollection sets = (KPCollection) o; int result = id > sets.id ? 1 : (id == sets.id ? 0 : -1); return result; } /*For Set end*/ public static void main(String args[]) { //Collection Collection<String> coll = new ArrayList<>(); coll.add("a"); //添加数据 coll.add("b"); coll.add("c"); Iterator<String> it = coll.iterator(); //创建迭代器 while (it.hasNext()) { String str = (String) it.next(); //获取集合中元素 System.out.println(str); } //List List<String> list = new ArrayList<>(); list.add("a"); //添加元素 list.add("b"); list.add("c"); list.add("d"); list.remove(2); //移除元素 list.set(0, "h"); for (int j = 0; j < list.size(); j++) { System.out.println(list.get(j)); //h b d } //Set KPCollection sets1 = new KPCollection("Li", 004); KPCollection sets2 = new KPCollection("Chen", 002); KPCollection sets3 = new KPCollection("Wang", 003); KPCollection sets4 = new KPCollection("Ma", 001); TreeSet<KPCollection> tree = new TreeSet<>(); tree.add(sets1); tree.add(sets2); tree.add(sets3); tree.add(sets4); Iterator<KPCollection> its = tree.iterator(); its = tree.headSet(sets2).iterator(); //its = tree.subSet(sets2, sets3).iterator(); //its = tree.tailSet(sets3).iterator(); while (its.hasNext()) { KPCollection sets = (KPCollection) its.next(); System.out.println(sets.id + " " + sets.name); } //Map Map<String,String> map = new HashMap<>(); map.put("01", "Li"); map.put("02", "Wei"); Set<String> setm = map.keySet(); //key Iterator<String> itmk = setm.iterator(); while (itmk.hasNext()) { String str1 = (String) itmk.next(); String str2 = (String) map.get(str1); System.out.println(str1+" "+str2); } Collection<String> collm = map.values(); //value Iterator<String> itmv = collm.iterator(); while (itmv.hasNext()) { System.out.println(itmv.next()); } } }
四、枚举和泛型
枚举可以取代常量的定义方式,本质上还是以类的形式存在;泛型主要的作用是解决类型安全问题,可以提供编译时的安全检查。
/**********枚举**********/ package com.kplayer.enums; public class KPEnums { enum FRUITS { APPLE("10"), ORANGE("20"), GRAPE("30"); private String price; public String getPrice(){ return price; } private FRUITS(){ //默认构造方法 } private FRUITS(String price){ //带参构造方法 this.price = price; } } public static void compare(FRUITS f) { for (int i = 0; i < FRUITS.values().length; i++) { System.out.println(FRUITS.values()[i].ordinal() + "." + f + " compare to " + FRUITS.values()[i] + ":" + f.compareTo(FRUITS.values()[i])); //比较 System.out.println(FRUITS.values()[i] + " " + FRUITS.values()[i].getPrice()); } } //主方法 public static void main(String[] args) { compare(FRUITS.valueOf("ORANGE")); } }
/**********泛型**********/ package com.kpalyer.generic; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; //定义泛型时声明数组类型 class ArrayClass<T> { private T[] array; //定义泛型数组 public void SetT(T[] array) { //SetT this.array = array; } public T[] getT() { //getT() return array; } } //集合类声明容器的元素 class MutiOverClass<K, V> { public Map<K, V> m = new HashMap<K, V>(); //ArrayList<E>, HashSet<E>, Vector<E> public void put(K k, V v) { //put m.put(k, v); } public V get(K k) { //get() return m.get(k); } } //限制泛型可用类型 class LimitClass<T extends List> { //默认构造函数 } public class KPGeneric { public static void main(String[] args) { //定义泛型时声明数组类型 ArrayClass<String> a = new ArrayClass<String>(); String[] array = { "mem1", "mem2", "mem3", "mem4", "mem5" }; a.SetT(array); //调用SetT()方法 for (int i = 0; i < a.getT().length; i++) { System.out.println(a.getT()[i]); //调用getT()方法 } //集合类声明容器的元素 MutiOverClass<Integer, String> mu = new MutiOverClass<Integer, String>(); for (int i = 0; i < 5; i++) { mu.put(i, "mem" + i); //调用put()方法 } for (int i = 0; i < mu.m.size(); i++) { System.out.println(mu.get(i)); //调用getT()方法 } //限制泛型可用类型 LimitClass<ArrayList> l1 = new LimitClass<ArrayList>(); LimitClass<LinkedList> l2 = new LimitClass<LinkedList>(); //LimitClass<HashMap> l3 = new LimitClass<HashMap>(); //Bound mismatch } }
五、异常处理
/**********异常处理**********/ package com.kplayer.exceptions; //自定义异常 class MyException extends Exception { public MyException(String ErrorMessagr) { //构造方法 super(ErrorMessagr); //父类构造方法 } } public class KPException { //定义方法,抛出异常 static int avg(int number1, int number2) throws MyException { if (number1 < 0 || number2 < 0) { throw new MyException("Negative!"); } if (number1 > 100 || number2 > 100) { throw new MyException("Too Large!"); } return (number1 + number2) / 2; } public static void main(String[] args) { try { //预定义异常 int age = Integer.parseInt("20L"); // 数据类型转换出错 System.out.println(age); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("Exception Test 1 over"); } try { //自定义异常 int result = avg(102, 150); System.out.println(result); } catch (MyException e) { System.out.println(e); } finally { System.out.println("Exception Test 2 over"); } } }
六、反射
学会通过反射访问构造方法/成员变量/成员方法,以及Annotation的定义和访问。
/**********反射**********/ package com.kplayer.reflect; import java.lang.annotation.*; @Target(ElementType.CONSTRUCTOR) @Retention(RetentionPolicy.RUNTIME) public @interface Constructor_Annotation { String value() default "默认构造方法"; } package com.kplayer.reflect; import java.lang.annotation.*; @Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) @Retention(RetentionPolicy.RUNTIME) public @interface Field_Method_Parameter_Annotation { String describe(); Class type() default void.class; } package com.kplayer.reflect; public class Record { @Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id; @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name; @Constructor_Annotation() public Record() { } @Constructor_Annotation("立即初始化构造方法") public Record( @Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id, @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) { this.id = id; this.name = name; } @Field_Method_Parameter_Annotation(describe = "获得编号", type = int.class) public int getId() { return id; } @Field_Method_Parameter_Annotation(describe = "设置编号") public void setId( @Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id) { this.id = id; } @Field_Method_Parameter_Annotation(describe = "获得姓名", type = String.class) public String getName() { return name; } @Field_Method_Parameter_Annotation(describe = "设置姓名") public void setName( @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) { this.name = name; } } package com.kplayer.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.annotation.*; class SimpleClass { private String s; protected int i, i2, i3; public double count; //构造方法 private SimpleClass() { } protected SimpleClass(String s, int i) { this.s = s; this.i = i; } public SimpleClass(String... strings) throws NumberFormatException { if (0 < strings.length) i = Integer.valueOf(strings[0]); if (1 < strings.length) i2 = Integer.valueOf(strings[1]); if (2 < strings.length) i3 = Integer.valueOf(strings[2]); } //成员方法 public double count(int count) { System.out.println("s=" + s + " i=" + i + " i2=" + i2 + " i3=" + i3); try{ this.count = i*0.1 + i2*0.2 + i3*0.3 + count; } catch(Exception e){ e.printStackTrace(); } return this.count; } } public class KPReflect { public static void main(String[] args) { SimpleClass example = new SimpleClass("10", "20", "30"); Class<? extends SimpleClass> exampleC = example.getClass(); //访问构造方法 Constructor[] declaredConstructors = exampleC.getDeclaredConstructors(); for (int i = 0; i < declaredConstructors.length; i++) { Constructor<?> constructor = declaredConstructors[i]; //遍历构造方法 //是否参数数量可变 System.out.println("isVarArgs=" + constructor.isVarArgs()); //参数类型 System.out.println("getParameterTypes="); Class[] parameterTypes = constructor.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } //异常类型 System.out.println("getExceptionTypes="); Class[] exceptionTypes = constructor.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } System.out.println(); } //访问成员变量 Field[] declaredFields = exampleC.getDeclaredFields(); for (int i = 0; i < declaredFields.length; i++) { Field field = declaredFields[i]; //遍历成员变量 //变量名称 System.out.println("varName=" + field.getName()); //变量类型 Class fieldType = field.getType(); System.out.println("varType=" + fieldType); } System.out.println(); //访问成员方法 Method[] declaredMethods = exampleC.getDeclaredMethods(); for (int i = 0; i < declaredMethods.length; i++) { Method method = declaredMethods[i]; // 遍历方法 System.out.println("methodName" + method.getName()); // 获得方法名称 //方法是否参数数量可变 System.out.println("method.isVarArgs=" + method.isVarArgs()); //获得方法所有参数类型 System.out.println("method.getParameterTypes="); Class[] parameterTypes = method.getParameterTypes(); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(" " + parameterTypes[j]); } //获得方法返回值类型 System.out.println("method.getReturnType=" + method.getReturnType()); //获得方法可能抛出的所有异常类型 System.out.println("method.getExceptionTypes="); Class[] exceptionTypes = method.getExceptionTypes(); for (int j = 0; j < exceptionTypes.length; j++) { System.out.println(" " + exceptionTypes[j]); } } /**********Annotation**********/ Class recordC = null; try { recordC = Class.forName("com.kplayer.reflect.Record"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println("------ 构造方法的描述如下 ------"); Constructor[] declaredConstructors2 = recordC .getDeclaredConstructors(); // 获得所有构造方法 for (int i = 0; i < declaredConstructors2.length; i++) { Constructor constructor = declaredConstructors2[i]; // 遍历构造方法 // 查看是否具有指定类型的注释 if (constructor .isAnnotationPresent(Constructor_Annotation.class)) { // 获得指定类型的注释 Constructor_Annotation ca = (Constructor_Annotation) constructor .getAnnotation(Constructor_Annotation.class); System.out.println(ca.value()); // 获得注释信息 } Annotation[][] parameterAnnotations = constructor .getParameterAnnotations(); // 获得参数的注释 for (int j = 0; j < parameterAnnotations.length; j++) { // 获得指定参数注释的长度 int length = parameterAnnotations[j].length; if (length == 0) // 如果长度为0则表示没有为该参数添加注释 System.out.println(" 未添加Annotation的参数"); else for (int k = 0; k < length; k++) { // 获得参数的注释 Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.print(" " + pa.describe()); // 获得参数描述 System.out.println(" " + pa.type()); // 获得参数类型 } } System.out.println(); } System.out.println(); System.out.println("-------- 字段的描述如下 --------"); Field[] declaredFields2 = recordC.getDeclaredFields(); // 获得所有字段 for (int i = 0; i < declaredFields2.length; i++) { Field field = declaredFields2[i]; // 遍历字段 // 查看是否具有指定类型的注释 if (field .isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { // 获得指定类型的注释 Field_Method_Parameter_Annotation fa = field .getAnnotation(Field_Method_Parameter_Annotation.class); System.out.print(" " + fa.describe()); // 获得字段的描述 System.out.println(" " + fa.type()); // 获得字段的类型 } } System.out.println(); System.out.println("-------- 方法的描述如下 --------"); Method[] methods = recordC.getDeclaredMethods(); // 获得所有方法 for (int i = 0; i < methods.length; i++) { Method method = methods[i]; // 遍历方法 // 查看是否具有指定类型的注释 if (method .isAnnotationPresent(Field_Method_Parameter_Annotation.class)) { // 获得指定类型的注释 Field_Method_Parameter_Annotation ma = method .getAnnotation(Field_Method_Parameter_Annotation.class); System.out.println(ma.describe()); // 获得方法的描述 System.out.println(ma.type()); // 获得方法的返回值类型 } Annotation[][] parameterAnnotations = method .getParameterAnnotations(); // 获得参数的注释 for (int j = 0; j < parameterAnnotations.length; j++) { int length = parameterAnnotations[j].length; // 获得指定参数注释的长度 if (length == 0) // 如果长度为0表示没有为该参数添加注释 System.out.println(" 未添加Annotation的参数"); else for (int k = 0; k < length; k++) { // 获得指定类型的注释 Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k]; System.out.print(" " + pa.describe()); // 获得参数的描述 System.out.println(" " + pa.type()); // 获得参数的类型 } } System.out.println(); } } }
七、多线程
掌握实现线程的两种方式,以及线程的生命周期,优先级,及同步机制。
/**********多线程**********/ package com.kplayer.thread; class KPThread extends Thread { //继承Thread类 private int count = 10; public synchronized void doit(){ //同步方法 if(count > 0){ try { Thread.sleep(100); //线程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count" + count--); } } public void run() { //重写 while (true) { doit(); } } } class KPRunnable implements Runnable{ //实现Runnable接口 int count = 10; public void run() { //重写 while (true) { synchronized(""){ //同步块 if(count > 0){ try { Thread.sleep(100); //线程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count" + count--); } } } } } public class KPMultiThread{ private Thread t1; private Thread t2; //匿名内部类 public KPMultiThread(){ t1 = new Thread(new Runnable() { int count = 21; public void run() { while (true) { try { Thread.sleep(1000); //线程休眠 t2.join(); //线程加入 } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(count+" "); if (++count == 30) { System.out.print(count+"\n"); return; } } } }); t1.start(); t2 = new Thread(new Runnable() { int count = 31; public void run() { while (true) { try { Thread.sleep(1000); //线程休眠 } catch (InterruptedException e) { e.printStackTrace(); } System.out.print(count+" "); if (++count == 40) { System.out.print(count+"\n"); return; } } } }); t2.start(); } public static void main(String[] args) { //继承Thread类 KPThread tt = new KPThread(); tt.start(); //实现Runnable接口 Thread tr1 = new Thread(new KPRunnable()); Thread tr2 = new Thread(new KPRunnable()); Thread tr3 = new Thread(new KPRunnable()); tr1.setPriority(3); //线程优先级 tr2.setPriority(2); tr3.setPriority(1); tr1.start(); tr2.start(); tr3.start(); //线程安全 KPRunnable tr = new KPRunnable(); Thread tr4 = new Thread(tr); Thread tr5 = new Thread(tr); Thread tr6 = new Thread(tr); tr4.start(); tr5.start(); tr6.start(); //线程休眠/加入 KPMultiThread mt = new KPMultiThread(); } }
注:部分代码来源于《Java从入门到精通(第3版)》——清华大学出版社