JAVA基础知识大总汇
2016-09-14 本文已影响831人
龙猫小爷
一 、对象和类
-
- final最终类,abstract抽象类,final和abstract是互斥的。
- final定义一个常量该常量一定要初始化(初始化详解:http://blog.csdn.net/jiafu1115/article/details/6734639 如何常量定义时没有立刻进行初始化,可以在构造函数、{}块、static块中进行初始化 ),static定义一个静态变量其属于类不属于类对象(因此static对象不能定义在方法中,也就是static不能是局部变量)。
- public\protected\private\默认访问权限
- 方法调用的参数:
- 基本类型作为参数:单值传递、单项传递,不会影响对应的实参;
- 复合类型作为参数:如果是一个类对象,在调用相应方法时系统会将该对象地址传递给形参;
- 方法不允许让一个对象参数引用一个新的对象。
- 静态方法
- 静态方法在访问本类成员时,只允许访问静态成员,不允许访问实例成员和方法;实例方法则无此限制。
- java允许类作为静态成员变量的类型
- static{ }
- 只能定义在类里,独立于任何方法,不能定义在方法里面
- 静态代码块里面的变量都是局部变量,只在本块内有效
- 在被类加载时自动执行
- 一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行
- 只能访问静态成员
-
二、继承与多态
- 所有的类都默认继承object类
- java继承的内存形态
- 父类中的成员被子类继承后,并非将其复制一份放到了子类控件中,它仍然只在父类空间中存一份
- 当使用成员时,先查找子类、再查找父类、依次往上,直到object类
- 属性隐藏:子类中的成员变量与父类同名,就可以将父类变量隐藏起来。无论修饰符、访问权限、数据类型、常量修饰符,只要同名就实现隐藏
- 方法覆盖:
- 覆盖必须满足三个条件:方法名相同;方法内的参数相同;若返回类型为基本类型,则返回类型必须完全相同;若返回类型为引用类型,必须与被重写方法返回类型相同或派生自卑重写方法的返回类型。如果方法内的参数不同则变成了重载
- 覆盖时访问权限只能更宽松,不能更严格
- 不能覆盖final方法
- 静态方法不允许被实例方法覆盖,实例方法也不允许被静态方法覆盖。
- 静态方法被子类的静态方法重写时,实质是父类的静态方法被隐藏。
- super关键词
- 可以使用super引用到父类被隐藏的变量和被覆盖的方法——super.变量名/方法名
- 使用super调用父类的构造方法——super([参数列表]):只能在构造方法中调用父类构造方法;只能是第一条执行语句;一个构造方法只能有一条super语句
- 多态:运行时的多态和编译时的多态
- 运行时多态:通过覆盖同名成员函数来实现,其调用规则是依据对象在实例化时而非定义时的类型相应地调用对应类中的同名成员函数
- 编译时多态:通过重载函数来实现,其调用规则依据对象在定义时的类型相应地调用对应类中的重载函数
- 方法重载:
- 方法区别:参数个数不同/对应位置上的参数类型不同;返回值不同无法区别;访问修饰符和final对重载没有影响(final方法可以被重载)
- 若每一参数都可以完全匹配则它就是最佳可行方法
- 若某方法的每一个参数匹配都不比其他方法差,且至少有一个参数比别的方法好,它就是最佳可行方法。byte-short-int-long-float-double和char-int-long-float-double
- 运行时的多态 (子类赋值给父类时,只有普通的方法才使用子类的,子类的普通成员变量、静态成员变量、静态方法都无法传递给父类)
- 定义一个父类变量,但在创建对象时使用子类的构造方法,这是允许的。并且对象可以使用子类的普通方法(如果是子类特有的方法,父类无法使用)
- java允许子类对象为父类变量赋值,但是父类对象不能为子类对象赋值
- 对于成员变量来说没有运行时的多态这个特性
- 静态方法没有运行时的多态这个特性
public class father {
public String name;
public static int age;
public father(String name,int age) {
this.name=name;
this.age=age;
}
public void print(){
System.out.println("这是父类的输出方法");
}
public static void printAge(){
System.out.println("这是爸爸的年龄");
}
public void isFather(){
System.out.println("我是爸爸");
}
}
public class son extends father{
public String name;
public static int age;
public son(String name, int age) {
super("爸爸", 50);
this.name=name;
this.age=age;
public void print(){
System.out.println("这是子类的输出方法");
}
public static void printAge(){
System.out.println("这是儿子的年龄");
}
public void isSon(){
System.out.println("我是儿子");
}
}
public class text {
public static void main(String[] args) {
son s=new son("儿子",20);
father f=s;
System.out.println(f.name+" "+f.age);
f.print();
f.printAge();
f.isFather();
//f.isSon()是错误的,这是子类特有的方法,父类无法使用
}
}
输出结果:
爸爸 50
这是子类的输出方法
这是爸爸的年龄
我是爸爸
- 接口
- 接口都是abstract,无需用abstract修饰
- 接口中的成员变量都是常量,使用public\static\final修饰,不允许使用protected\private,且必须要赋初值(因为接口成员自动默认为static final,虽然可以省略不写,所以必须赋初值)
- 接口中的方法都是抽象的(使用static 和default 关键字可以使方法有方法体)
- abstract与static不可联合使用(同时声明static和abstract,用类名调用一个抽象方法肯定不行)
- 除了静态方法可以有方法体,其他任何方法都不可以有方法体;任何方法都不可以用final修饰
- 接口不能被实例化,因此没有构造函数
- Illegal modifier for the interface method f; only public, abstract, default, static and strictfp are permitted
- 抽象类与抽象方法
- 抽象类只能作为父类,不能实例化。抽象方法总是用在抽象类与接口中。
- 构造方法、静态方法、private方法、final方法不能声明abstract
- 明确声明有abstract方法;从抽象类中继承但没有实现全部抽象方法;实现一个接口但没有实现所有抽象方法。均为抽象类
三、字符串
- String的使用方法
- String str="abc",则"abc"存放在内存中的字符串常量区并将该引用赋给str;String str=new String("abc"),则str在堆区创建了字符串对象。
-
- String.replaceAll("遵循正则表达式","替换语句")
- void getChars(int sourceStart,int sourceEnd,char target[],int targetStart) 截取多个字符,targetStart表示开始复制的下标
- equals()和equalsIgnoreCase() 比较两个字符串
- lastIndexOf() 查找字符或者子串是后一次出现的地方。
- StringBuffer的使用方法(线程安全)
- StringBuilder的使用方法
- StringBuilder 是一个可变的字符序列。它继承于AbstractStringBuilder,实现了CharSequence接口。
- String,StringBuffer,StringBuilder区别:http://blog.csdn.net/clam_clam/article/details/6831345
四、JAVA输入输出处理技术
- IO流分类及功能说明:一种是字节流(BYTE),一次读写8位二进制数;一种是字符流(CHARACTER),一次读写16位二进制数。
- 以字节为导向的输入流(InputStream):
- 以字节为导向的输出流(OutputStream):
- 以UNICODE字符为导向的输入流(Reader):
- 以UNICODE字符为导向的输出流(Writer):
- 用于封装以字节为导向的,一下主要用来修饰InputStream系列的各种输入:
- 用于封装以字符为导向的,主要用来修饰Reader系列的各种输入:
- 用于封装以字节为导向的,主要用来修饰OutputStream系列的各种输出:
- 用于封装以字符为导向的,主要用来修饰Write系列的各种输出:
- InputStream和OutputStream所提供的一些基本方法:
- FileInputStream和FileOutputStream的使用
public static void main(Stings[] args){
FileInputStream fis;
FileOutputStream fos;
int ch; //读入用户输入的字符,使用Int类型不使用char类型
try{
//可以使用文件file,或者文件名,或者文件描述符来生成文件输入流
fis=new FileInputStream(FileDescriptor.in)
fos=new FileOutputStream("demo.txt");
//反复读入用户输入的字符,并保存至文件中,知道输入回车符
while((ch=fis.read())!='\r') //还有判断ch是否为-1
fos.write(ch);
fis.close();
fos.close();
}catch(Exception e){}
}
- SequenceInputStream——顺序输入流:将多个输入流顺序连接在一起。在进行输入时,顺序输入流依次打开每个输入流并读取数据,在读取完毕后将该流关闭,然后自动切换到下一个输入流。
SequenceInputStream(Enumeration e):创建一个串行输入流,连接枚举对象e中的所有输入流
SequenceInputStream(InputStream is1,InputStream is2):创建一个串行输入流,连接is1和is2
- PipedInputStream、PipedOutputStream——管道输入输出流:可以实现程序内部线程间的通信或不同程序间的通信。
- PipedInputStream作为接收端,PipedOutputStream作为发送端,两者必须进行连接之后才能通信。
- 连接方法1——构造方法:PipedInputStream(PipedOutputStream src)或者PipedOutputStream(PipedInputStream src)
- 连接方法2——利用管道输入输出流提供的connect()方法进行连接,PipedInputStream.connect(PipedOutputStream src)
- FilterInputStream、FilterOutputStream——过滤输入输出流:建立在基本的输入输出流之上,能够对基本输入输出流所传输的数据进行指定类型或者格式的转换,即可实现对二进制字节数据的理解和编码转换。
- 构造方法:DataInputStream(InputStream in)或者DataOutputStream(OutputStream os)
- 读数据的方法:readByte()、readBoolean()、readChar()、readInt()、readFloat()、readDouble()
- 写数据的方法:writeByte()、writeBoolean()、writeChar()、writeInt()、writeFloat()、writeDouble()
- Scanner使用方法:
- 格式化输出Printf
System.out.printf("<格式控制字符串>","<参数表>")
- “格式控制字符串”是由个0个或多个格式转换说明组成的一个字符串序列。一般格式为:%[格式修饰符]格式转换符。
- 格式说明包括5类字符:%、普通字符、转义字符、输出格式转换符以及格式修饰符。
- 格式转换符及其作用:
- 格式修饰符及其作用:
- File类及其方法
- 当程序创建一个File类对象时,并没有真正创建或准备创建一个文件,也不会去打开对应的文件,只是获取了文件的相关信息而已。File类没有提供任何对文件内容进行读写的方法,但提供了两个方法:mkdir()和createNewFile()。
- 文件随机访问——RandomAccessFile
- RandomAccessFile可以任意地访问文件的任何地方。此类对象包含一个记录指针,用于标识当前流的读写位置,这个位置可以向前移动,也可以向后移动,通过指针移动的方式实现对文件的随机访问。构造方法中的参数mode有4中模式:r——以只读方式打开文件,rw——以读写方式打开文件,rws\rwd——以读写方式打开文件,但写的时候不使用缓冲。
五、JAVA的多线程机制
- 并发:是对于单核处理器来说的,多个线程交替获取CPU资源。并行:对于多核处理器来说的,进程可以运行在不同的CPU上。http://www.2cto.com/kf/201409/330226.html
- 多线程的状态:新建、就绪、运行、阻塞、死亡
- Thread类
- 利用Threa类创建一个线程,必须创建一个从Thread类导出的新的子类。必须覆盖Thread的run()方法来完成线程的业务工作。当启动线程时必须调用Thread的start()函数。
-
- 构造方法:
- 常用方法:
- Runnable接口:当使用该接口时,不能直接创建所需类的对象并运行它,必须从Thread类的一个实例内部运行它。在实际编程中,实现Runnable的子类中,通常都会定义一个Thread类的对象,然后利用Thread的构造方法。
public class ThreadRunnable implements Runnable{
private Thread thread;
public void run(){//添加在线程中运行的方法}
public ThreadRunnable(String name){
thread=new Thread(this,name);
}
public void start(){
thread.start();
}
}
- join()方法等待子线程结束,确保主线程最后结束。
- setPriority()为线程设置优先级,1~10,默认值为5.
- 线程的调度与通信
- 进程间的互斥和同步,必须要使用信号量。JAVA中,信号量需要用户自己管理,系统只提供了起到PV原语作用的3个方法以及1个关键字:wait()——告知被调用的线程放弃管程进入睡眠,直到其他线程进入相同管程并且调用了notify();notify()——恢复相同对象中第一个调用wait()的线程;notifyAll()——恢复相同对象中所有调用wait()的线程。具有最高优先级的线程最先运行。
- Synchronized关键字用来标志被同步使用的资源。资源可以是数据、方法或者一段代码。被Synchronized修饰的资源,系统会为它分配一个管程,保证在某一时间内,只有一个线程对象在享有这一资源。上面三个方法,都只能使用在Synchronized控制的代码块中。
- 生产者—消费者问题
public class Commodity {
private int count = 0;
private int MAX_CONTAIN = 6;
private int a[] = new int[MAX_CONTAIN];
// 将商品存入
public synchronized void put(int n) {
try {
while (count >= MAX_CONTAIN)
wait();
a[count++] = n;
System.out.println("放入"+n);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 将商品取出
public synchronized void get() {
try {
while (count <= 0)
wait();
System.out.println("取出"+a[--count]);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Thread1 extends Thread {//生产者
private Commodity commodity;
public Thread1(Commodity commodity) {
this.commodity=commodity;
}
@Override
public void run() {
for(int i=0;i<20;i++){
int n=new Random().nextInt(1000);
commodity.put(n);
}
}
}
public class Thread2 extends Thread {//消费者
private Commodity commodity;
public Thread2(Commodity commodity) {
this.commodity=commodity;
}
@Override
public void run() {
for(int i=0;i<20;i++){
commodity.get();
}
}
}
public class ThreadDemo {
private static Commodity commodity=new Commodity();
private static Thread1 thread1=new Thread1(commodity);
private static Thread2 thread2=new Thread2(commodity);
public static void main(String[] args) {
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
六、运行时类型识别
- RTTI(Run-Time Type Identification 运行时类型识别)是任何一门面向对象的语言都必须提供的功能,不仅系统本身要利用该功能来识别目前正在运行的对象真正所属的类别,程序员有时候也需要利用这一机制来识别对象。
- RTTI的工作原理
- Class包含了与类有关的信息。任何一个作为程序一部分的类,都有一个Class对象。在运行期间,一旦程序员想生成某个类的一个对象,用于执行程序的JVM首先会检查该类型的Class对象是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。
- Class.forName()方法用来加载一个对象。可以不使用new关键字来创建对象。它是一个静态方法,返回的是一个Class对象。所以无法使用加载类中的一些方法和数据。
- new创建对象要通过编译器静态检查,如果编译时类不存在,那么使用该对象的类也无法通过编译。而forName()方法是动态加载,即便编译时类不存在,编译也可以通过,只是运行时会抛出异常。
- Java类的识别方法
- 使用getClass方法获取类信息:该方法是Object类中的一个最终方法,所有类都可以使用它,但是不能覆盖它。
Class c=类对象.getClass(); //获取到实际所属的类
c1.getName(); //获取类名
- 使用类标记:如果T是任意的java类型,T.class就代表匹配的类对象。
Class c1=类对象.getClass();
c1==类.class //使用==来进行类型判断
- 使用关键字instanceof判断所属类:objectName(对象名) instanceof className(类名)
- 利用反射(Reflection)获取运行时类信息
- 它允许运行中的java程序对自身进行检查,并能直接操作程序的内部属性。反射中三个类最为重要:Field、Method和Constructor,它们分别描述类的成员属性、方法和构造器。这三个类都有一个getName()方法,可以返回相应条目的名称。
Class c=Class.forName(...);
Method[] m=c.getDeclareMethods();//获取类中声明的方法
- 使用isInstance()方法判断所属类:isInstance(Object obj)。
- 获取成员方法信息:如果想要获取父类的方法,需要在程序中使用getMethods()方法。
Class c1=Class.forName(...);
Method mList[]=c1.getDeclareMethods();//获取类方法,保存在方法数组中
Method m=mList[i];
Class pvec[]=m.getParameterTypes();//显示所有方法的参数类型
Class evec[]=m.getExceptionType();//显示所有方法可能抛出的异常
- 获取构造方法信息
Class c=Class.forName(...);
Constructor ctorlist[]=c.getDeclaredConstructors();//获取类的构造方法
- 获取类的成员属性:如果要获取父类的属性,使用getFields()
Class c=Class.forName(...);
Field fieldList[]=c.getDeclaredFields();//获取成员属性列表
Field f=fieldList[i];
int mod=f.getModifiers();//获取成员修饰符
Modifier.toString(mod);//返回以官方顺序排列的字符串描述
七、泛型
- 普通泛型
public class Generic<T>{
T obj;
Generic(T o){
ob=o;
}
T getObj(){
return obj;
}
}
- 参数类型T不能使用在静态方法中。
- Java的编译器并不会创建多个不同版本的Generic类。相反,编译器会删除所有的泛型信息,并进行必要的强制类型转换,这个过程被称为擦拭或者擦除。
- 用new返回的引用必须是Generic<Integer>类型,无论是省略Integer,还是将其改成其他类型,都会导致编译错误。
Generic<Integer> g=new Generic<Integer>;
- 传递给形参的实参必须是类类型,而不能使用int或者char之类的简单类型。
- 有界类型
- 在指定一个类型参数时,可以指定一个上界,声明所有的实际类型都必须是这个超类的直接或者间接子类。
class classname<T extends superclass>
- 接口也可以用来作上界,使用的关键词还是extends。界限类型用“&”分隔。在多个界限中,可以有多个接口,但最多只能有一个类。如果用一个类作为界限,则它必须是界限列表中的第一个。
- java提供的通配符“?”,使用形式为:genericClassName<?>
- 通配符无法将上界改变得超出泛型类声明时的上界范围。
- 通配符用来声明一个泛型类的变量的,而不能创建一个泛型类。
- 泛型方法
- 泛型方法常用的形式
[访问权限修饰符] [static] [final] <类型参数列表> 返回值类型 方法名([形式参数列表]
- 泛型方法可以写在泛型类中,也可以写在普通类中。
- 类型参数可以用在方法体中修饰局部变量,也可以用在方法的参数表中,修饰形式参数。
- 泛型方法可以是实例方法或是静态方法。类型参数可以使用在静态方法中,这是与泛型类的重要区别。
- 泛型接口
interface 接口名<类型参数表>
-
- 以泛型类为父类:泛型类的子类必须将泛型父类所需要的类型参数,沿着继承链向上传递。所以这个子类也必须是泛型类。
public class a<T> extends b<T>//这两个类型参数必须用相同的标识符T
- 运行时类型识别
- 泛型类的对象总是一个特定的类型,它不再是泛型。所有的类型查询都只会产生原始类型,无论是getClass()方法,还是instanceof操作符。
//a是Generic<Integer>类型
a instanceof Generic<?>//<>里面只能写通配符?,不能写Integer之类确定的类
- 当用某泛型子类来测试是否为父类对象时,结果也为真。
- 强制类型转换:泛型类的对象也可以采用强制类型转换,转换成另外的泛型类型,不过只有当两者在各个方面兼容时才能这么做。只能将子类转换成父类,不能将父类转换成子类。
- 继承规则:
//以下的用法是错误的
Generic<Number> oa=new Generic<Integer>;
- 擦拭
- 在生成的java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数会在编译器编译的时候去掉。这个过程被称为类型擦拭。
- 类型擦除可以简单地理解为将泛型java代码转换为普通的java代码。例如:List<String>和List<Object>等在编译后都会编程List。
- T占据的位置会被Object代替,如果类型参数指定了上界,那么就会用上界类型来代替它。
- 擦拭带来的错误
- 静态成员不可以使用类型参数或者是本泛型类的对象。因为静态成员是独立于任何对象,也可以在对象创建之前就被使用。此时,编译器无法知道用哪一个具体的类型来替代T,所以编译器不允许这样使用。
- 重在冲突
//在编译时,T会被Object所取代,所以这两个实际上声明的是同一个方法
void conflict(T o){}
void confilct(Object o){}
- 接口实现问题
//在编译时都被擦除成Comparable,所以这实际上实现了同一个接口。要实现泛型接口,只能实现具有不同擦除效果的接口
Class foo implements Comparable<Integer>,Comparable<Long>
- 泛型的局限
- 不能使用基本类型。
- 不能使用泛型类异常。
- 不能使用泛型数组。
- 不能实例化参数类型对象。
八、Java集合框架
- 了解hashCode和equals:http://www.cnblogs.com/dolphin0520/p/3681042.html
- Java集合接口层次
- 主要核心有3类:List、Set、Map。List和Set都继承了Collection,而Map则独成一体。
-
- Collection接口
- 该接口提供了很多的方法进行操作。
- Iterator iterator()——该方法用于返回一个能够实现Iterator接口的对象,此对象也被称为迭代器。可以使用这个迭代对象,逐个访问集合中的对象。
Object next()
boolean hasNext()
void remove()//用于删除上次调用next()方法取出的目标对象
- Set接口
- Set接口继承Collection接口 ,而且它不允许集合中存在重复项。具体的Set实现类依赖添加的对象的equals()方法来检查等同性。
- Set接口有连个具体的实现类:HashSet和TreeSet。
- HashSet是为优化查询速度而设计的Set,添加到HashSet对象需要采用恰当分配散列码的方式来实现hashCode()方法。
- TreeSet是一个有序Set,添加到TreeSet的元素也必须是可排序的。
- List接口
- Map接口
- Map接口方法分成3组操作:改变、查询和提供可选视图。
- 改变:允许从映射中添加和除去键值对。键值对都可以是Null。但是不能把Map作为一个键或值添加给自身。
Object put(Object key,Object values)
Object remove(Obejct key)
void putAll(Map mapping)
void clear()
- 查询:这一操作指的是允许检查映射内容,可以从一个映射空间键取得另一个空间的值。
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
- 可选视图:允许把键或值得组作为集合来处理。
public Set keySet()
public Collection values()
public Set entrySet()//返回一个实现Map.Entry接口的对象集合
-
- HashSet
- 在记录存储位置和关键字之间建立一个确定的函数对应关系f,是每个关键字和记录中一个卫衣的存储位置相对应。我们称这个对应关系f为哈希函数,按照这个思想建立的表成为哈希表或者散列表。
- 哈希函数的设计有很多方法:直接定址法、数字分析法、平方取中法、折叠法、除留余数法。
- 哈希解决冲突办法:http://xiaolu123456.iteye.com/blog/1485349
- 使用迭代器进行逐个查找,没有解决常用的查找功能。
- TreeSet
- 有序集,内部的元素按照一定的顺序组织起来的。当用迭代器访问该集合时,各个元素将按照排序之后的顺序出现。
- 无法完成普通查找,只能通过迭代器进行查找。
-
- TreeMap
- 提供了根据关键字查找相应记录的功能。
-
九、类型包装器、自动装箱和元数据
- 元数据:指用来描述数据的数据,更通俗一点就是描述代码间的关系,或者代码与其他资源之间内在的联系数据。元数据可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。
- 注解的定义及语法
- 建立一个注解需要通过接口机制
@interface MyAnno{//告诉编译器正在声明一个注解类型
String str();//所有的注解都只有成员方法,而且不需要提供这些方法的实现
int val();
}
- 一旦定义了一个注解,就可以用它来注解一个声明,任何类型的声明都可以加上一个注解。例如:类、方法、属性、参数和枚举常量都可以被注解,甚至是注解本身也可以被注解。注解在任何情况下都要在声明的最前面。
- 注解的保留策略
- RetentionPolicy.SOURCE\CLASS\RUNTIME
- SOURCE:注解只在源文件中保留,在编译期间删除。
- CLASS:在编译期间存储在.class文件中,但在运行时不能通过JVM来获得。
- RUNTIME:在编译期间存储在.class文件中,且运行时可以通过JVM来获得。
- 默认保留策略为CLASS
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno{
............
}
- 使用反射读取注解
- 使用getAnnotation()方法
//注解是在某类的doSomething方法上
Class c=Class.forName(类名);
//获得doSomething方法
Method m=c.getMethod("doSomething");
//获取方法注解
MyAnno anno=m.getAnnotation(MyAnno.class);
- 存在多个注解时使用
Annotation[] getAnnotations();
- 在使用注解时,没有为注解的成员指定值,可以让他们使用默认值
type member() default value
- 标记注解的应用:不包括成员的特殊注解,唯一的目的是为了标记一个声明
- 确定是否存在标记注解的最佳途径是使用方法:isAnnotationPresent()返回值是boolean
methoad.isAnnotationPresent(注解接口名)//判断注解是否存在
- 内置注解的应用
- @Retention:只能作为另一个注解的注解,描述保留策略。
- @Documented:标记注解,告诉工具一个注解将被文档化。只能用作对一个注解声明的注解。
- @Target:指定一个注解可以运用的声明的类型。只能用作另外一个注解的注解。参数是ElementType枚举类型的一个常量。这个常量指定注解可以运用的声明的类型。
@Target({ElementType.FIELD,ElementType.LOCAL_VARIABLE})
- @Inherited:它是一个标记,只能用于另外一个注解声明,而且它只影响使用类声明的注解。它使得父类的注解能被子类所继承。因此,当对子类查询特定的注解时,如果该注解不在子类中,则会检查它的父类。如果在父类中,而且使用了@Inherited注解,那么该注解被返回。
- @Override:标记注解,只适用于方法。该注解的方法必须覆盖父类中的同一方法,否则会发生编译错误。
- @Deprecated:标记注解,表明一个声明已经过时,被一个新格式的声明所替代。
- @SuppressWarnings:指定一个或多个可由编译器发布并将被处理的警告。
十、常用工具类
- Runtime类:每个java应用程序都会创建一个Runtime类的实例,通过该实例,应用程序可以和运行环境进行交互操作。通过getRuntime()方法来获取Runtime对象的引用。
- 常用方法:
- 执行其他程序:Java程序可以调用操作系统中存在的其他进程,调用exec()方法就可以了。
Runtime run=Runtime.getRuntime();
run.exec("....");
- 有时候,需要等待被启动的程序结束后,才结束本程序,这就需要用到exec()返回的Process对象。该对象有一个waitFor()方法,必须等到被执行的程序结束该方法才返回。另外,Process对象还有一个方法:exitValue(),可以获取程序的返回值。正常为0,不正常为非0。
- System类的使用
-
- currentTimeMillis()以毫秒为单位获取计算机上的时间,返回一个long型的值,记录与1970.1.1之间的时间差。
- exit()退出方法:System.exit(0);
- Math类的使用
- 数学函数包括:随机函数、三角函数、指数函数、取整函数等。提供两个静态成员变量:E和PI。
- Random类的使用
- 正则表达式
- 普通字符和转义字符:就是直接的一个确定字符,无需赘述。
- 与多种字符匹配的表达式:\d(任意一个数字,即0~9中任意一个);\D(匹配所有的非数字字符);\w(任意一个字母、数字或者下划线);\W(匹配与所有\w不匹配的字符);\s(包括空格、制表符、换页符等空白字符之中的任意一个);\S(用于匹配除单个空格符之外的所有字符);.(匹配除换行符以外的任意一个字符)。
- 自定义能够匹配多种字符的表达式:[ ]包含一系列字符,能够匹配其中任意一个字符。用[^]包含一系列字符,则能够匹配其中字符之外的任意一个字符。例如:[a-z0-9]
- 修饰匹配次数的特殊字符:{n}(表达式重复n次);{m,n}(表达式至少重复m次,最多重复n次);{m,}(表达式至少重复m次);?(匹配表达式0次或1次);+(表达式至少出现1次);*(表达式不出现或出现任意次)。例如:a{2}b{2,3}
- 其他一些代表抽象意义的特殊符号:^(与字符串开始的地方匹配,不匹配任何字符);$(与字符串结束的地方匹配,不匹配任何字符)。若要求匹配的是整个字符串的内容,而不是字符串中的一部分,此时可以使用^和$加以说明。例如^a*$表示任意个“a”组成的字符串,而“a*”表示匹配整个字符串或其子串。
- \b(匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符。http://www.cnblogs.com/newsouls/p/3781812.html );\B(匹配非单词边界,即左右两边都是\w范围或者左右两边都不是\w范围时的字符缝隙)。若要求匹配的是一整个单词而不是单词的一部分,这时候就要使用\b。例如:“\bTom\b”对“Tommy Tom”进行匹配,只会匹配后面的Tom。
- 影响表达式内部的自表达式之间的关系:|(或关系,匹配左边或者右边);()(括号中的表达式可以作为整体被修饰)。
- 重复匹配不定次数的表达式在匹配过程中,总是尽可能多地匹配,这种匹配原则叫“贪婪模式”。在修饰匹配次数的特殊符号后再加上一个“?”号,则可以时匹配次数不定的表达式尽可能少地匹配,使可匹配可不匹配的表达式尽可能地“不匹配”。例如:对字符串“abbbabbba”进行匹配,若使用正则式“a[\w]+a”进行匹配,其会按照贪婪模式进行匹配,匹配到的内容为“abbbabbba”;若使用“a[\w]+?a”进行匹配,其会按照非贪婪模式进行匹配,匹配到的内容为“abbba”。
- 反向引用:“\n”匹配第n个括号。例如:对于分组正则式“((23)(45))”,其中包括三个分组“2345”、“23”、“45”,编号分别为1、2、3。“((23)(45))\1”表示对“23452345”进行匹配,“((23)(45))\2”表示对“234523”进行匹配。
- Pattern类的使用
- Pattern中存储了一个经过编译的正则表达式,它也提供简单的正则表达式匹配功能。而Matcher对象是一个状态机,它依据Pattern对象作为匹配模式,对字符串展开匹配检查。
- 一个正则表达式必须先编译成为一个Pattern类的实例,然后使用这个Pattern对象的matcher()方法来生成一个Matcher实例,接着便可以使用该Matcher实例以编译的正则表达式为基础,对目标字符串进行匹配工作。
- Matcher类的使用
-
Pattern p=Pattern.compile("\bTh"); //使用\\b则表示转义字符
Matcher m=p.matcher(text);
m.matches();
m.find();
m.lookingAt();