天天看点

牛客上的JAVA错题集合

DBMS事务的四大特性

数据库事务的四大特性分别是:原子性、一致性、隔离性和持久性。

特性 说明 实现
一致性 在一个事务执行之前和执行之后数据库都必须处于一致性状态。假如数据库的状态满足所有的完整性约束,也可以说数据库是一致的 DBMS的完整性子系统实现
原子性 事务是一组不可分割的操作单元,这组单元要么同时成功要么同时失败 DBMS的事务管理子系统实现
隔离性 多个用户的事物之间不能相互影响,需要相互隔离 DBMS的并发控制子系统实现
持久性 一个事务一旦提交,那么它对数据库产生的影响就是永久不可逆的,如果后面在回滚或者出现异常,都不会影响已提交的事务 DBMS的恢复管理子系统实现

Object中的方法

protected Object clone()创建并返回此对象的一个副本。 

boolean equals(Object obj)指示其他某个对象是否与此对象“相等”。  

protected void finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。  

class  getClass()返回此 Object 的运行时类。  

int hashCode()返回该对象的哈希码值。  

void notify()唤醒在此对象监视器上等待的单个线程。  

void notifyAll()唤醒在此对象监视器上等待的所有线程。  

String toString()返回该对象的字符串表示。  

void wait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。  

void wait(long timeout)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。  

void wait(long timeout, int nanos)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

数组的声明

在java 中,声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能对给定数组长度.。

String  a[]  ;String[] a = new String[11];

String a[11] 是错误的。

内部类

作用:

实现了更好的封装,我们知道,普通类(非内部类)的访问修饰符不能为private或protected,而内部类可以。当我们将内部类声明为private时,只有外部类可以访问内部类,很好地隐藏了内部类。

内部类可以继承(extends)或实现(implements)其他的类或接口,而不受外部类的影响。

内部类可以直接访问外部类的字段和方法,即使是用private修饰的,相反的,外部类不能直接访问内部类的成员。

 内部类是一个编译时的概念,编译后会生成两个独立的class文件

成员内部类

    成员内部类可以看成是外部类的一个成员,在成员内部类中无法声明静态成员,但static

    final字段是个例外。我们知道加载类时,会先初始化静态成员,如果成员内部类有静态成

    员,那么内部类就会在外部类之前生成,而内部类是为外部类服务的,内部类在外部类之

    前就生成可能会脱离掌控。在实例化成员内部类时,成员内部类会持有一个外部类当前对

    象的引用,这样在成员内部类中就可以直接访问外部类的成员,即使是private修饰的。

局部内部类

  局部内部类的使用和成员内部类的使用基本一致,只是局部内部类定义在外部类的方法中,就

  像局部变量一样,并不是外部类的成员。局部内部类在方法外是无法访问到的,但它的实例可

  以从方法中返回,并且实例在不再被引用之前会一直存在。局部内部类也可以访问所在方法的

  局部变量、方法参数等,限制是局部变量或方法参数只有在声明为final时才能被访问。 

匿名内部类

  可以把匿名内部类想象成是没有类名的局部内部类,匿名内部类有以下特点:

   1、匿名内部类不能有构造器,匿名内部类没有类名,肯定无法声明构造器。

   2、匿名内部类必须继承或实现一个接口,指定给new的类型为匿名类的超类型,匿名类不

      能有显示的extends或implements子句,也不能有任何修饰符。

   3、匿名内部类和成员内部类、局部内部类一样,也不能声明静态成员。

静态内部类

  静态内部类,有的书上也称为嵌套类,声明它时需要用static修饰符,静态内部类不同于前三

  种内部类,静态内部类不会持有外部类当前对象的引用,所以在静态内部类中无法访问外部

  类的非静态成员,可以这么说,静态内部类不依赖于外部类。

String的“传值” 

String在java中是一个特殊的类型,它不属于基本数据类型,也不能传递引用,主要原因是String的本质是一个被final修饰是char数组,每次更新String的值,它都会默认创建一个新的String,这样原本的String和更新后的String就不是同一个String,所有指向也就不同。

 方法的重载(overload)和重写(override)   //java多态性的体现

方法的重写是对于继承关系而言,子类继承父类,重写父类的方法,规则是方法名、参数名、返回类型,抛出对象类型都要和父类的方法相同。

方法的重载体现的多态性,在一个类中,一个方法名可以有多种不同的功能,规则是方法名相同、参数名、参数个数,返回类型可以不同。与方法的返回值类型与访问权限无关

 Java编码形式

Java中的char是Unicode编码。

Unicode编码占两个字节,就是16位,足够存储一个汉字。

 java编译运行指令dos窗口

javac test.java    这是编译,javac + 文件名.java  进行编译    javac 的对象文件     

java test    只是执行,执行的是.class 文件   但是不能  java test.class       java执行的对象是.class 文件

接口和抽象类的区别

牛客上的JAVA错题集合

抽象类

特点: 

1.抽象类中可以构造方法 

2.抽象类中可以存在普通属性,方法,静态属性和方法。 

3.抽象类中可以存在抽象方法。 

4.如果一个类中有一个抽象方法,那么当前类一定是抽象类;抽象类中不一定有抽象方法。 

5.抽象类中的抽象方法,需要有子类实现,如果子类不实现,则子类也需要定义为抽象的。 

6,抽象类不能被实例化,抽象类和抽象方法必须被abstract修饰

关键字使用注意: 

抽象类中的抽象方法(其前有abstract修饰)不能用private、static、synchronized、native访问修饰符修饰。

接口

1.在接口中只有方法的声明,没有方法体。 

2.在接口中只有常量,因为定义的变量,在编译的时候都会默认加上public static final 

3.在接口中的方法,永远都被public来修饰。 

4.接口中没有构造方法,也不能实例化接口的对象。(所以接口不能继承类) 

5.接口可以实现多继承 

6.接口中定义的方法都需要有实现类来实现,如果实现类不能实现接口中的所有方法则实现类定义为抽象类。 

7,接口可以继承接口,用extends

不同类型之间的运算 

byte→short(char)→int→long→float→double

 synchronized关键字和volatile关键字

volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。

多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞

volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。

volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

 volatile的特性

 (1)保证可见性,不保证原子性

     a.当写一个volatile变量时,JMM会把该线程本地内存中的变量强制刷新到主内存中去;

     b.这个写会操作会导致其他线程中的缓存无效。

   (2)禁止指令重排 

     重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。重排序需要遵守一定规则:

  a.重排序操作不会对存在数据依赖关系的操作进行重排序。

        比如:a=1;b=a; 这个指令序列,由于第二个操作依赖于第一个操作,所以在编译时和处理器运

     行时这两个操作不会被重排序。

    b.重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果不能被改变

      比如:a=1;b=2;c=a+b这三个操作,第一步(a=1)和第二步(b=2)由于不存在数据依赖关系, 所以可能会发 

    生重排序,但是c=a+b这个操作是不会被重排序的,因为需要保证最终的结果一定是c=a+b=3。

 Thread.yield()方法

Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。

        yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保

证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!

      举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,

有可能是其他人先上车了,也有可能是Yield先上车了。

     但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,

最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。

yield()不会释放锁标志。

 Java线程中的方法

1、sleep()

使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。

例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了。

总之,sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。

2、join()

join()方法使调用该方法的线程在此之前执行完毕,也就是等待该方法的线程执行完毕后再往下继续执行。注意该方法也需要捕捉异常。

3、yield()

该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。

4、wait()和notify()、notifyAll()

这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用。synchronized关键字用于保护共享数据,阻止其他线程对共享数据的存取,但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。

wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。

notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

 Java子类构造规则

 如果子类构造器没有显示地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中有没有显示地调用超类的其他构造器,则Java编译器将报告错误。使用super调用构造器的语句必须是子类构造器的第一条语句。

 静态类规范

静态方法不可以使用非静态变量

 Java权限大小

public可以被当前类,子类,包,其他包,访问,

protected 可以被当前类,子类,包访问

default可以被可以被当前类,包内访问;

private只能被当前类访问

default不能修饰变量

 包装类和基本数据类---Integer

总体主要分为两个方面

①比较的是值

一、基本数据类型与引用数据类型进行比较时,引用数据类型会进行拆箱,然后与基本数据类型进行值的比较

举例:

int i = 12;

Integer j = new Integer(12);

i == j 返回的是true

二、引用数据类型与基本数据类型进行比较(equals方法),基本数据类型会进行自动装箱,与引用数据类型进行比较,Object中的equals方法比较的是地址,但是Integer类已经重写了equals方法,只要两个对象的值相同,则可视为同一对象,具体看API文档,所以这归根到底也是值的比较!

举例:

int i = 12;

Integer j = new Integer(12);

j.equals(i) 返回的是true

②比较的是地址

一、如果引用数据类型是这样 Integer i = 12;直接从常量池取对象,这是如果数值是在-128与127之间,则视为同一对象,否则视为不同对象

举例:

Integer i = 12; Integer j = 12; i == j 返回的是true

Integer i = 128; Integer j = 128; i == j 返回的是false

二、如果引用数据类型是直接new的话,不管值是否相同,这时两个对象都是不相同的,因为都会各自在堆内存中开辟一块空间

举例:

Integer i =new Integer(12);

Integer j = new Integer(12);

i == j 这时返回的是false

三、从常量池取对象跟new出来的对象也是不同的

举例:

Integer i = 12;

Integer j = new Integer(12)

i == j 这时返回的是false,因为第二个语句其实已经是new了两个对象了!!!

数据传输的量与质量 

数据传输速率(Data Transfer Rate):是描述数据传输系统的重要技术指标之一。数据传输速率在数值上等于每秒钟传输构成数据代码的比特数。

误码率(SER:symbol error rate):是衡量数据在规定时间内数据传输精确性的指标。误码率=传输中的误码/所传输的总码数*100%。

吞吐率:指一个业务系统在单位时间内提供的产量(或服务量)。在计算机或数据通信系统,指的是单位时间内通过某通信信道(a communication channel)或某个节点成功交付数据的平均速率,通常以每秒比特数(bps, bits per second )为单位。

 关于public和类和main()方法

一个文件中,可以有多个public class
public class Main { public class Inner{

    }
}
           

即,外部类为public,还可以有public的内部类。

B.一个文件中可以有多个类,可以是多个并列的类,也可以是外部类、内部类结合。

C.一个类中,可以有多个main方法,这是重载,但是public static void main(String[] args)的方法只能有一个。

D.类中,可以有main方法,也可以没有main方法,而有一个main()方法的时候,也可以是任意访问权限。因为这个类不一定要执行,可以只是辅助类。

public class MainTest { void main(){
    }
}
           

 关于final的说法

修饰类

   当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。

修饰方法

父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的。

此处需要注意的一点是:因为重写的前提是子类可以从父类中继承此方法,如果父类中final修饰的方法同时访问控制权限为private,将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是在子类中重新定义了新的方法。(注:类的private方法会隐式地被指定为final方法。)、

修饰变量

当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。(final要求值,即地址的值不发生变化。)

final修饰一个成员变量(属性),必须要显示初始化。

最终类 

最终类就是被final修饰的类,最终方法就是被final修饰的方法。最终类不能被继承,最终方法不能被重写。

 null的用途

一、null是代表不确定的对象

Java中,null是一个保留字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。

比如:int a = null;是错误的。Ojbect o = null是正确的。

Java中,变量的适用都遵循一个原则,先定义,并且初始化后,才可以使用。我们不能int a后,不给a指定值,就去打印a的值。这条对对于引用类型变量也是适用的。

有时候,我们定义一个引用类型变量,在刚开始的时候,无法给出一个确定的值,但是不指定值,程序可能会在try语句块中初始化值。这时候,我们下面使用变量的时候就会报错。这时候,可以先给变量指定一个null值,问题就解决了。例如:

Connection conn = null;

try {

conn = DriverManager.getConnection("url", "user", "password");

} catch (SQLException e) {

e.printStackTrace();

}

String catalog = conn.getCatalog();

如果刚开始的时候不指定conn = null,则最后一句就会报错。

二、null本身不是对象,也不是Objcet的实例

null本身虽然能代表一个不确定的对象,但就null本身来说,它不是对象,也不知道什么类型,也不是java.lang.Object的实例。

可以做一个简单的例子:

//null是对象吗? 属于Object类型吗?

if (null instanceof java.lang.Object) {

System.out.println("null属于java.lang.Object类型");

} else {

System.out.println("null不属于java.lang.Object类型");

}

结果会输出:null不属于java.lang.Object类型

三、Java默认给变量赋值

在定义变量的时候,如果定义后没有给变量赋值,则Java在运行时会自动给变量赋值。赋值原则是整数类型int、byte、short、long的自动赋值为0,带小数点的float、double自动赋值为0.0,boolean的自动赋值为false,其他各供引用类型变量自动赋值为null。

这个具体可以通过调试来看。

四、容器类型与null

List:允许重复元素,可以加入任意多个null。

Set:不允许重复元素,最多可以加入一个null。

Map:Map的key最多可以加入一个null,value字段没有限制。

数组:基本类型数组,定义后,如果不给定初始值,则java运行时会自动给定值。引用类型数组,不给定初始值,则所有的元素值为null。

五、null的其他作用

1、判断一个引用类型数据是否null。 用==来判断。

2、释放内存,让一个非null的引用类型变量指向null。这样这个对象就不再被任何对象应用了。等待JVM垃圾回收机制去回收。

java的默认基本类型

java中整型默认的是int,浮点默认的是double.    float   a = 0.1  是错误的。  需要加入f

 形式参数

//定义两个变量a,b;

int a=1;

int b=2;

//方法sum中a,b是实际参数传递给形参

Sum(a,b);

//此方法中定义的a,b变量是形式参数

public static int Sum(int a,int b)

{

A:形式参数可被视为local variable。形参和局部变量一样都不能离开方法。都只有在方法内才会发生作用,也只有在方法中使用,不会在方法外可见。

B: 对于形式参数只能用final修饰符,其它任何修饰符都会引起编译器错误。但是用这个修饰符也有一定的限制,就是在方法中不能对参数做任何修改。 不过一般情况下,一个方法的形参不用final修饰。只有在特殊情况下,那就是:方法内部类。  一个方法内的内部类如果使用了这个方法的参数或者局部变量的话,这个参数或局部变量应该是final。 

C:形参的值在调用时根据调用者更改,实参则用自身的值更改形参的值(指针、引用皆在此列),也就是说真正被传递的是实参。

D:方法的参数列表指定要传递给方法什么样的信息,采用的都是对象的形式。因此,在参数列表中必须指定每个所传递对象的类型及名字。想JAVA中任何传递对象的场合一样,这里传递的实际上也是引用,并且引用的类型必须正确。--《Thinking in JAVA》

 Tread中的run 方法和start()方法

public

class

Bground

extends

Thread{

public

static

void

main(String argv[]){

Bground b =

new

Bground();

b.run();

}

public

void

start(){

for

(

int

i=

;i<

10

;i++){

System.out.println(

"Value of i = "

+i);

}

}

}

对于线程而言,start是让线程从new变成runnable。run方法才是执行体的入口。

但是在Thread中,run方法是个空方法,没有具体实现。

Bground继承了Thread,但是没有重写run方法,那么调用run方法肯定是无输出。

Tread中有run方法,编译可以通过

java中的exe对应的工具 

java,exe是java虚拟机

javadoc.exe用来制作java文档

jdb.exe是java的调试器

javaprof,exe是剖析工具

jsp中静态include和动态include的区别 

动态 INCLUDE 用 jsp:include 动作实现 <jsp:include page="included.jsp" flush="true" /> 它总是会检查所含文件中的变化 , 适合用于包含动态页面 , 并且可以带参数。各个文件分别先编译,然后组合成一个文件。

静态 INCLUDE 用 include 伪码实现 , 定不会检查所含文件的变化 , 适用于包含静态页面 <%@ include file="included.htm" %> 。先将文件的代码被原封不动地加入到了主页面从而合成一个文件,然后再进行翻译,此时不允许有相同的变量。 

以下是对 include 两种用法的区别 , 主要有两个方面的不同 ;

    一 : 执行时间上 :

    <%@ include file="relativeURI"%> 是在翻译阶段执行

    <jsp:include page="relativeURI" flush="true" /> 在请求处理阶段执行 .

    二 : 引入内容的不同 :

    <%@ include file="relativeURI"%>

    引入静态文本 (html,jsp), 在 JSP 页面被转化成 servlet 之前和它融和到一起 .

    <jsp:include page="relativeURI" flush="true" /> 引入执行页面或 servlet 所生成的应答文本 .

 Java中的关键字

Java中的关键字有哪些?

答:1)48个关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。

2)2个保留字(现在没用以后可能用到作为关键字):goto、const。

3)3个特殊直接量:true、false、null。 

 局部和成员变量赋值

定义在类中的变量是类的成员变量,可以不进行初始化,Java会自动进行初始化,如果是引用类型默认初始化为null,如果是基本类型例如int则会默认初始化为0

局部变量是定义在方法中的变量,必须要进行初始化,否则不同通过编译

正则表达式中的字符 

元字符 描述
\ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\\n”匹配\n。“\n”匹配换行符。序列“\\”匹配“\”而“\(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置 。
$ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于o{0,}
+ 匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多的匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少的匹配“o”,得到结果 ['o', 'o', 'o', 'o']
.点 匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。
(pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用0…0…9属性。要匹配圆括号字符,请使用“”或“”或“”。
(?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern) 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)

非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。这个地方不正确,有问题

此处用或任意一项都不能超过2位,如“(?<!95|98|NT|20)Windows正确,“(?<!95|980|NT|20)Windows 报错,若是单独使用则无限制,如(?<!2000)Windows 正确匹配

x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[zf]ood”则匹配“zood”或“food”。
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
[a-z]

字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。

注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.

[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d 匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
\D 匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。

 常见ASCII码

常见字符的ASCII码值如下:空格的ASCII码值为32;数字0到9的ASCII码值分别为48到57;大写字母“A”到“Z”的ASCII码值分别为65到90;小写字母“a”到“z”的ASCII码值分别为97到到122。
           

 new URL("链接")

我们在执行URL u =new URL("http://www.123.com");这句话的时候确实要抛出异常,但是这个异常属于IOException,不管网址是否存在,最后都会返回该网址的一个连接,打印出来就是该网址。

 范型是否会影响执行速度

泛型仅仅是java的一颗语法糖,它不会影响java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的。

 containsKey

在HashMap中改成containsKey和containsValue方法来替换。

HashMap和HashTable 

关于HashMap的一些说法:

a)  HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。HashMap的底层结构是一个数组,数组中的每一项是一条链表。

b)  HashMap的实例有俩个参数影响其性能: “初始容量” 和 装填因子。

c)  HashMap实现不同步,线程不安全。  HashTable线程安全

d)  HashMap中的key-value都是存储在Entry中的。

e)  HashMap可以存null键和null值,不保证元素的顺序恒久不变,它的底层使用的是数组和链表,通过hashCode()方法和equals方法保证键的唯一性

f)  解决冲突主要有三种方法:定址法,拉链法,再散列法。HashMap是采用拉链法解决哈希冲突的。

注: 链表法是将相同hash值的对象组成一个链表放在hash值对应的槽位;

   用开放定址法解决冲突的做法是:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。 沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。

  拉链法解决冲突的做法是: 将所有关键字为同义词的结点链接在同一个单链表中 。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于1,但一般均取α≤1。拉链法适合未规定元素的大小。

2.  Hashtable和HashMap的区别:

a)   继承不同。

 public class Hashtable extends Dictionary implements Map

public class HashMap extends  AbstractMap implements Map

b)  Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

c)  Hashtable 中, key 和 value 都不允许出现 null 值。 在 HashMap 中, null 可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为 null 。当 get() 方法返回 null 值时,即可以表示 HashMap 中没有该键,也可以表示该键所对应的值为 null 。因此,在 HashMap 中不能由 get() 方法来判断 HashMap 中是否存在某个键, 而应该用 containsKey() 方法来判断。

d)  两个遍历方式的内部实现上不同。Hashtable、HashMap都使用了Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

e)  哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

f)  Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

注:  HashSet子类依靠hashCode()和equal()方法来区分重复元素。

     HashSet内部使用Map保存数据,即将HashSet的数据作为Map的key值保存,这也是HashSet中元素不能重复的原因。而Map中保存key值的,会去判断当前Map中是否含有该Key对象,内部是先通过key的hashCode,确定有相同的hashCode之后,再通过equals方法判断是否相同。

 try catch finally

1.try块是必须的,catch块和finally块都是可选的,但必须存在一个或都存在。try块不能单独存在。

    2.try块里的语句运行中出现异常会跳过try块里其他语句,直接运行catch里的语句。

    3.无论try块中是否有异常,无论catch块中的语句是否实现,都会执行finally块里的语句。

    4.如果try块或catch块中有return语句,finally块里的语句会执行在try块或catch块中的return语句前。

    5.如果finally块里有return语句,则直接返回,而不执行try块或catch块里的return语句。

    6.只有一种办法不执行finally块里的语句,那就是调用System.exit(1);方法,即退出java虚拟机。

    强调:finally块里的语句在try或catch里的人return前执行!!!

可以把try finally 理解成一个栈,当try里面有return 时,结束。当try finally 都有return时,就按照顺序来,先执行try里的return ,return的值保存在栈中,继续执行下面的finally中的代码,遇到return则就覆盖前面栈中return的值,形成新的值返回。

 ArraryList三种遍历的删除

1.普通for循环:可以删除

        注意每次删除之后索引要--

2.Iterator遍历:可以删除

        不过要使用Iterator类中的remove方法,如果用List中的remove方法会报错

3.增强for循环foreach:不能删除

        强制用List中的remove方法会报错

Integer的封装和拆箱 

intValue()是把Integer对象类型变成int的基础数据类型; 

parseInt()是把String 变成int的基础数据类型; 

Valueof()是把String 转化成Integer对象类型;(现在JDK版本支持自动装箱拆箱了。)

两个字符

两个字符串相加,相当于new String(a+b),相当于创建一个新对象。

System.out.println()的包名 

System是java.lang包下的一个类,out为System的final静态成员(PrintStream类型),println()是PrintStream类的实例方法。

类的加载顺序 

(1) 父类静态代码块(包括静态初始化块,静态属性,但不包括静态方法)

(2) 子类静态代码块(包括静态初始化块,静态属性,但不包括静态方法 )

(3) 父类非静态代码块( 包括非静态初始化块,非静态属性 )

(4) 父类构造函数

(5) 子类非静态代码块 ( 包括非静态初始化块,非静态属性 )

(6) 子类构造函数

其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)

Base b = new Sub();它为多态的一种表现形式,声明是Base,实现是Sub类, 理解为 b 编译时表现为Base类特性,运行时表现为Sub类特性。

几种数组复制方法的效率

总结: 

(1)从速度上看:System.arraycopy > clone > Arrays.copyOf > for 

(2)for的速度之所以最慢是因为下标表示法每次都从起点开始寻位到指定下标处(现代编译器应该对其有进行优化,改为指针),另外就是它每一次循环都要判断一次是否达到数组最大长度和进行一次额外的记录下标值的加法运算。 

(3)查看Arrays.copyOf的源码可以发现,它其实本质上是调用了System.arraycopy。之所以时间差距比较大,是因为很大一部分开销全花在了Math.min函数上了。

@interface 自定义注解

@retention(RetentionPolicy.RUNTIME)
@Target(ElementType.method)
public @interface Annotation{
    int value();
    String  str()  default "str" ;
}
           
@Target(ElementType.xxx)注解中的参数可以有
  1. ANNOTATION_TYPE 注解类型声明
  2. CONSTRUCTOR构造方法声明
  3. FIELD 字段声明(包括枚举常量)
  4. LOCAL_VARIABLE 局部变量声明
  5. METHOD方法声明
  6. PACKAGE包声明
  7. PARAMETER参数声明
  8. TYPE类、接口(包括注解类型)或枚举声明
@retention(RetentionPolicy.xxx)的参数有
  1. RetentionPolicy.SOURCE:给编译器看,编译器编译后该类型的注解就被丢弃掉了。(生成的.class字节码文件中,将不再存在该类型的注解)
  2. RetentionPolicy.CLASS:字节码级别的,给类加载器看的,在类被加载时做一些引导相关的一些操作。编译器编译保留(在.class字节码文件中保留),类加载器加载时使用,加载后丢弃掉。
  3. RetentionPolicy.RUNTIME:给JVM看的,编译器编译后保留,类加载器加载保留,在运行时,JVM使用。通常自定义的注解都是使用该保留域,在程序运行时反射注解中的信息,并根据属性的值做相关的操作。

注解中的属性名称用name()的形式表示,没有default的属性必须在将来使用注解时设置参数,有default则可以不需要。

注解属性的类型基本数据类型、类、枚举、注解、String等,以及以上类型的一维数组。

继续阅读