4.13-4.19 一周总结
日子过的很快,五分之一的培训生活就这样过去了。总结这一个月,到现在为止,至少也才算是java的入门,了解了java的架构和语法,要想自己静下心来,独立的去完成一个开发,也根本是没什么信心。在过去的一周里,学习了java的一些难点,集合框架、范型、异常、反射和注释,整体而言自己的接受能力还是不错的,不过深入的不够,总是浅尝辄止,这也是一直以来自己学习的通病,所以这个一定要改变。因为一旦进入企业,没有那么多的学习机会,企业需要的是一来就能上手的动手高手。所以动手能力自己一定要锻炼。
理理上周的知识点:
1.范型:范型是编译时概念,在运行时没有泛型。增强了java的类型安全,可以在编译期间对容器内的对象进行类型检查,在运行期间不必进行类型的转换。
①子类元组的参数的参数一般都包含父类的元组。
Public class MyClass<I,T> extends HaHa<I>;
②任何范型类都是原生类型的子类。
Gen rob=new Gen<String>(“hah”); 定义了一个Gen<String>范型类,它是它的原生类Gen的子类。不过如果调用方法的话还是需要强转成String类型的。
③范型类关系和参数化类型无关。
(如果G是泛型类,无论A和B是什么关系,G(A)和G(B)之间没有任何关系)
Gen<Employee> gc=new Gen<Manager>(new Manager(“hah”,20)); 错误。
虽然Manager是Empoyee的子类,但是这只是类之间的关系。实例一下,经理餐厅和员工餐厅是不一样的,你不能说经理餐厅是员工餐厅的一种。
Gen<Employee> gc=new Gen<Employee>(new Manager(“hah”,20));
这样就可以了,相当于员工餐厅中new一个经理出来,因为经理也是员工,也可能在员工餐厅就餐。
④参数化类型相同时,范型类关系可以保持。
Gen<String> g=new Gen2<String,Integer>(“”,25);
⑤范型参数值不适用基本数据类型。
Gen<int> g=new Gen<int>(25); 这个是错误的。
⑥不可实例化数据类型是范型参数的类。
Public Pair(){first=new T();}
⑦不可实例化数据类型是范型参数的数组。
⑧<T extends Comparable>让泛型的数据类型实现Comparable接口,就可以调用其方法compareTo方法。
<T extends Person> T是Person或者Peron的子类类型。
<T extends Person & Comparable &Seralizable>如果是多个,用&连接。
⑨范型的通配符。
<?>可以使用任意类型,但不能使用get和set方法,只可以用作运算。
<? Extends 类型>表示这个类型是某个类型或者其子类。可以get,不能set
<? Super 类型>表示这个类型是这个类型或者其父类。可以set,不能get
父类可以set,子类可以get。
⑩范型方法的定义
把数组拷贝到集合时,数组的类型一定要和集合的泛型相同。
在方法的修饰符和返回值之间定义范型。
Public static <T> T getFirst(T[] arr){return arr[0];}
static <E extends Number & Comparable> void copyArrayToList(E[] os,List<E> lst){……} //定义泛型的范围类在前,接口在后
static<E , V extends E> void copyArrayToList(E[] os,List<E> lst){……} //定义多个泛型,"super"只能用在泛型的通配符上,不能用在泛型的定义上
⑪泛型定义的时候,只能使用extends 不能使用super,只能向下,不能向上。 调用时用<?> 定义时用<E>
⑫范型类的定义:
类的静态方法不能使用泛型,因为泛型类是在创建对象的时候产生的。
Public class ArrayList<E>{private E[] data;public ArralyList(){
data=(E)new Object[10];}}
2.异常
一.常见的三种异常
Error类是致命的,它是所有错误类的父类。Exception类是所有异常类的父类,他们同时Throwable的子类。
①Error:不可恢复的错误,程序员无法处理,整个程序停下修改。
②Runtime exception:运行时异常,编译时不管,所以又叫未检查异常,由于程序员没有细心检查造成的,如空指针异常、对未实例化的对象调用其方法。
常见的未检查异常:
算术异常:java.lang.ArithmeticException 除0,负数开平方根
空指针异常:java.lang.NullPointerException “.”前面对象空了
数组下标越界异常:java.lang.ArrayIndexoutofBoundsException
安全性异常:java.lang.SecurityException
类型转换异常:ClassCastException
数字格式异常:NumberFormatException 对字母进行了转化为数字时
这类异常不要求处理,直接进行编码修改,直到成功。
③其它异常,称为已检查异常,这类异常并非人为产生的。但当程序员在编写代码时,要事先做好应急的预案。try{…}catch(E e) {…}finally{…}
ClassNotFound Exception,DataFormat Exception.IOException
二.产生异常的过程:
①JVM生成异常对象,包含异常相关信息。
②JVM抛出异常,寻求解决方案,抛给调用者。
③调用者如果不处理的话,继续上抛。
④如果main方法不处理的话,JVM会终止程序。
三.异常的处理
①声明抛出异常:不在方法内处理异常,而是把异常抛出到调用方法中。
也可以抛出多个异常Public void openThisFile(String fileName)throws java.io.FileNotFoundExctption,java.lang.ClassNotFoundExctption{//code for method};
②捕获异常:
捕获,已处理,不再抛出
抛出,继续抛出,异常传播
try{ //1 次;只可以出现一次
code 1;
code 2;
code 3;
}catch( Exception ex ){ //0-n 次;可以出现多次,但要求异常由
小到大或是平级的
Code 4;
ex.printStackTrace();
}finally{ //0-1 次;如无catch,finally 必须出现一次
code 5;
}
code 6;
如不发生异常;try+finally
如发生异常,try(发生异常后try 中断) ―> catch ―> finally
发生了异常,即使捕获,try 也会被中止。
执行try 中的代码,正常,没出现异常,则会接着执行finally 块中的代码;
如果在try 块中代码出现了异常,而且catch 要捕获的异常类型和抛出的相同,
异常被捕获,并进行处理,处理完成后,执行finally 块中的代码。
没有异常,要执行的代码有:1,2,3,5,6
代码2 抛出异常,被捕获:1,2,4,5,6
代码3 抛出异常,但捕获不了:1,2,3,5 -> 中止程序
}catch( xxException e ){
code 4;
}catch( BException e ){
code 5;
}
范围大的异常要写在后面,范围小的异常要写在前面。
finally 中代码无论如何都会被执行的。
如果在try 块中最后写上return 0,finally 中的代码块同样要被执行
只有System.exit(0)时,finally 中代码不会做,其余情况都会做的。
不管try catch 中返回了什么值,只要finally 中有return,那么finally 中的return有效
throws 类型,出现在声明部分,可以跟着多个异常类型,用逗号隔开。
throw 一个对象,在方法体实现中
throw new RuntimeException(未检查异常);//此时,整个程序停掉。
e.printStackTrace();//输出异常栈消息
三.自定义异常
步骤:
(1)继承Exception
(2)写无参构造和String 作参数构造
public class AgeException extends RuntimeException{ //
将异常细分
public AgeException(){}
public AgeException( String msg ){
super(msg); //设置异常详细信息
}
}
//class Person
Public void setAge( int age ) throws AgeException{
If( age <= 0 || age>=150)
throw new AgeException(“age error”);
this.age = age;
}
//main
Person p = new Person();
try{
p.setAge( 178 ); //throws or try…catch
} catch ( AgeException e ){
e.printStackTrace();
}
四.如何确定何种异常处理方式
如不能确定异常如何处理:thorws
如能完全确定,try…catch
3. 反射
1. 用途:开发工具、框架等。比如开发Hibernate、依赖注入就是用反射技术来生成一套代码。所以,反射最大特点是针对通用编程,避免了硬编码.
2. Class类。字节码文件(.class)读到JVM中,其文件对象保存在Class对象中,也就是说类加载的时候就会产生Class对象。且Class类是私有的,所以不能new对象。
如何获得一个类的类对象?有如下三中方法:
(1) Class c1=String.class; //类名加.class 前提为知道类名
Class i1=int.class;(8种基本数据类型也可以)
Class i2=Integer.TYPE;(返回的是int的类对象)
(2) Student s1=new Student(" SONG"); //通过类的对象得到类对象
Class c2=s1.getClass(); //得到Student 所属类的类对象
例如:
String s1=”123”;
String s2=”456”;
Class c1=s1.getClass();
Class c2=s2.getClass(); c1==c2 的判断结果为true. 全类只有一个类对象
最常见也最灵活的方式:
(3) String className=”java.lang.String”; //用字符串当参数
Class c3=Class.forName(className); //静态方法。会发生类加载
有可能此类未被加载,则要先加载(通过类名找到文件加载),再返回类对象。
注意:类名应写全限定名。即包名+类名 使用场合为类名存在字符串中时。
3.Java 类反射中的主要方法
对于以下两类组件中的任何一类来说-- 构造函数和方法-- java.lang.Class
提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。
java.lang.reflect
Method Constructor Field
以下是用于查找构造函数的一组反射调用:
Constructor getConstructor(Class[] params) 获得使用特殊的参数类型的公共构造函数
Constructor[] getConstructors() -- 获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数
Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数
用于获得方法信息函数:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获得类声明的所有方法
4.反射更大的功能: 通过普通对象,得到类的对象。能操纵这个类。
对类对象调用newInstance() 则用无参构造方法构造一个其对象
Object o1=new Student(); //直接生成一个对象
Class c=Class.forName(“Student”);//得到这个对象的Class类对象
Object o1=c.newInstance();//通过类对象获得类的对象
Student s2=new Student(“SongYuZhou”,23);