Java笔记

InputStream输入流以字节为单位来获取数据,而且需要复杂的判断并创建字节数组作为缓冲,最主要的是字节转换为字符时容易出现中文乱码的情况,所以对于字符数据的读取,应该使用扫描器进行封装,然后获取字符串型的数据
实现两个变量之间的交换不使用第三个变量:
                A = A^B;
B = A^B;
A = A^B;

不同类型属性取得hashcode值的方式
boolean   hashcode=(f:0?1);
整数类型(byte,short,char,int)   hashcode=(int)f;
long         hashcode=(int)(f^(f>>>32));
float         hashcode=Float.floatToIntBits(f);
double     hashcode=(int)(Double.doubleToIntBits(f)^(Double.doubleToIntBits(f)>>>32));
引用类型   f.hashCode();
在对Switch多分支判断,该语句只支持对常量的判断,而常量又只能是Java的基本数据类型,虽然在以后的jdk版本中可以对String类的字符串对象进行判断,还有一种做法就是把String类的hashCode()方法返回值作为Switch语句的表达式。
不要忽略负数:例如,“N%2==1"本来是用来计算数字N是否为奇数的,但是如果没有考虑到负数的情况话,会导致这个算法的失败,因为任何负数应用这个算法都会等于-1;
在jdk1.5之前使用for循环对集合,数值和迭代器进行遍历,需要创建索引变量,条件表达式,这样会造成代码混乱,并增加出错的几率,并且每次循环中索引变量或迭代器都会出现3次,有两次出错的机会,而且会有一些性能损失,其性能稍微落后于foreach循环。
创建只接受整数的文本框控件 
new JFormattedTextField(NumberFormat.getInstance());

Map集合的具体实现,HashmMap只允许一条记录的健为null,但是却不限制集合中值为null的数量。HashTable实现一个映射,它不允许任何键值为空。TreeMap集合将对集合中的键值排序,默认排序方式为升序。

split()方法接受一个正则表达式字符串作为参数,可以使用"|"定义多个分隔符。

所有局部变量都是放在栈内存里保存的,不管其是基本类型的变量,还是引用类型的变量,都是存储在各自的方法栈区,但引用类型变量所引用的对象(包括数组,普通Java对象)则总是存储在堆内存中。

从语法角度来看,程序可以在3个地方对实例变量执行初始化:
1.定义实例变量时指定初始值。
2.非静态初始化块中对实例变量指定初始值。
3.构造器中对实例变量指定初始值。
其中第1,2中方式比第3种方式更早执行,但第1,2种方式的执行顺序与他们在源程序中的排列顺序相同。

当创建任何Java对象时,程序总会先依次调用每个父类非静态初始化块,父类构造器(总是从object开始)执行初始化,最后才调用本类的非静态初始化块,构造器执行初始化。

构造器只是负责对Java对象实例变量执行初始化(也就是赋初始化值),在执行构造器代码之前,该对象所占的内存已经被分配下来,这些内存里值都是默认是空值----对于基本类型的变量,默认的空值就是0或者false;对于引用类型的变量,默认的空值就是null;

当this在构造器中时,this代表正在初始化的Java对象。

当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际所引用的对象决定。

注意:如果父类构造器调用了被子类重写的方法,且通过子类构造器来创建子类对象,调用(不管是显式还是隐式)了这个父类构造器,就会导致子类的重写方法在子类构造器的所有代码之前被执行,从而导致子类的重写方法访问不到子类的实例变量值的情形。

对于普通实例变量,java程序可以对它执行默认的初始化,也就是将实例变量的值指定为默认的初始值0或null,但对于final实例变量,则必须由程序员显式指定初始值。

对于一个使用final修饰的变量而言,如果定义该final变量时就指定初始值,而且这个初始值可以在编译时就确定下来,那么这个final变量将不再是一个变量,系统会将其当成“宏变量”处理。也就是说,所有出现该变量的地方,系统将直接把它当成对应的值出来。(直接量赋值,或者被赋的表达式只是基本的算术运算表达式或字符串连接运算,没有访问普通变量,调用方法)

对于final实例变量而言,只有在定义该变量时指定初始值才会有“宏变量”的效果,在非静态初始化块,构造器中为final实例变量指定初始值则不会有这种效果。

在任何内部类(局部内部类)中访问的局部变量都应该使用final修饰。内部类可能扩大局部变量的作用域,再者变量的值如果可以随意改变,那将引起极大的混乱。

增大负载因子可以减少Hash表(就是那个Entry数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作(HashMap的get()与put()方法都要用到查询),减少负载因子会提高数据查询的性能,但会降低Hash表所占用的内存空间。

所有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了哟个PRESENT,它是一个静态的Object对象。当新放入HashMap的Entry中key与集合中原有Entry的key相同(HashCode()返回值相等,通过equals比较也返回true)时,新添加的Entry的value将覆盖原来Entry的value,但key不会有任何改变。

TreeSet采用红黑树来保存集合中的Entry,这意味着TreeMap添加元素,取出元素的性能都要比HashMap低。

从序列化机制的角度来看,ArrayList的实现比Vector的实现更安全,Vector其实就是ArrayList的线程安全版本。

当程序把LinkedList当成双端队列,栈使用,调用addFirst(E e),addLast( E e),getFirst(E e),getLast(E e),offer(E e),offerLast(E e),offerFirst(E e)等方法来操作集合元素时,LinkedList可以快速定位需要操作的元素,因此LinkedList总是具有较好的性能表现。

Iterator迭代器只负责对各种集合所包含的元素经行迭代,它自己并没有保留集合元素,因此使用Iterator进行迭代时,通常不应该删除集合元素,否则将引发ConcurrentModificationException异常。实际上,对于ArrayList,Vector,LinkedList等List集合而言,当使用Iterator遍历他们时,如果正在遍历倒数第二个集合元素,使用List集合众的remove()方法删除集合的任意一个元素斌斌不会引发ConcurrentModificationException异常(遍历将提前结束,Iterator不会访问List集合的最后一个元素)。对于TreeSet,HashSet等Set集合而言,当使用Iterator遍历它们时,如果正在遍历最后一个集合元素,使用Set集合的remove()方法删除集合的任意并不会引发ConcurrentModificationException异常,当正在遍历其他元素时删除集合任意元素都将引发异常(如果当前正在遍历集合的最后一个元素,也就是集合遍历操作已经完成)。Next()方法中调用checkForComodifiction()检查集合是否被修改。

软引用(SoftReference)当系统内存空间足够时,它不会被系统回收,程序也可以使用该对象;当系统内存空间不足时,系统将会回收它。
弱引用(WeakReference)当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。垃圾回收具有一定的不确定性。
虚引用(PhantomReference)主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列(ReferenceQueue)联合使用。

垃圾回收机制主要完成下面两件事情
1.跟踪并监控每个Java对象,当某个对象处于不可达状态时,回收该对象所占用的内存;
2.清理内存分配,回收过程中产生的内存碎片;

三代堆内存:
Young---由一个Eden区和2个Survivor区构成。绝大多数对象先分配到Eden区中(有一些大的对象可能会直接被分配到Old代中),Survivor区重的对象都至少在Young代中经历狗一次垃圾回收,所以这些对象在被转移到Old代之前会先保留在Survivor空间中。当Young代进行回收,垃圾回收机制采用较高的频率对Young代进行扫描和回收(通常采用复制算法),这种回收的系统开销比较小,因此被称为(minor collection)。
Old---当Old代的内存将要用完时,垃圾回收机制会进行全回收,也就是对Young代和Old代都用进行回收(通常会采用标记压缩算法),此时回收成本就大得多,被称为主要回收(major collection)。
Permanent---主要用于装载Class,方法等信息,默认为64M,垃圾回收机制通常不会回收Permanent代中对象。

-Xmx:设置Java虚拟机堆内存的最大容量。
-Xms:设置Java虚拟机堆内存的初始容量。
-XX:MinHeapFreeRadio=40 :设置Java堆内存最小的空闲百分比,默认值为40.
-XX:MaxHeapFreeRadio=70:设置Java堆内存最大的空闲百分比,默认值为70.
-XX:NewRadio=2:设置Yong/Old内存的比例。
-XX:NewSize=size:设置Young代内存的默认容量。
-XX:SurvivorRadio=8:设置Young代中eden/survivor的比例。
-XX:MaxNewSize=size:设置Young代内存的最大容量。
-XX:PermSize=size:设置Permanent代内存的默认容量。
-XX:MaxPermSize=64m:设置Permanent代内存的最大容量。

当需要使用字符串,还有Byte,Short,Integer,Long,Float,Double,Boolean,Character包装类的实例时,程序不应该采用new的方式来创建对象,而应该直接采用直接量才创建它们。

Java创建对象的常规方法:
1.通过new调用构造器创建Java对象。
2.通过Class对象的newInstance()方法调用构造器创建Java对象。
3.通过Java的反序列机制从IO流中恢复Java对象。
4.通过Java对象提供的clone()方法复制一个新的Java对象。
对于字符串,还有Byte,Short,Integer,Long,Float,Double,Boolean,Character包装类以直接量来创建对象。
也可以通过简单的算术表达式,连接运算来创建Java对象。

System提供的identityHashCode()静态方法用于获取某个对象唯一的hashcode值,这个identityHashCode()的返回值与该类是否重写了hashcode()方法无关,只有当两个对象相同,它们的identityHashCode值才会相等。

在没有多线程的环境下,应该优先使用StringBuilder类来表示字符串。

复合赋值运算符中包含隐式类型转换。可能导致计算结果的高位被"截断",从而导致实际数据丢失的情形。
E1 op= E2 (其中op可以是+,-,*,/,%,<<,>>,>>>,&,^,|等双目运算符)等价于如下语句E1 = (E1的类型)(E1 op E2)
但如果把+当成字符串连接运算符使用,则+=运算符左边的变量只能是String类型,而不可能是String的父类型(如Object或CharSequence等)。

Java程序中通常不能包含"全角字符",但Java程序的字符串中完全可以包含"全角字符",Java程序的注释中也可以包含"全角字符".且注释的字符必须合法。

Java提供了3中方式来表示字符:
直接使用单引号括起来的字符值。
使用转义字符。
使用Unicode转义字符。(Java对Unicode转义字符不会进行任何特殊的处理,它只是简单地将Unicode转义字符替换成相应的字符。

当把一个带泛型信息的Java对象赋给不带泛型信息的变量时,Java程序会发生擦除,这种擦除不仅擦除使用该Java类时传入的类型实参,而且会擦除所有的泛型信息,也就是擦除所有尖括号里的信息。

注意:replace(CharSequence target,CharSequence replacement)
            replaceAll(String regex,String replacement)

从jdk1.5开始,java编译器增加了更严格的检查,只要在javac命令后增加-Xlint:fallthrough选项,java编译器就会提示缺少break等警告。

switch表达式只能是以下数据类型:byte,short,int,char,enum,String。不能是long,float,double等其他基本类型。

if---else必须先处理小范围的条件,后处理大范围的条件,才能除去漏下的条件。

for循环的初始化条件可以同时定义多个变量,但由于它只能接受一条语句,因此这两个变量的数据类型应该相同。

浮点数作循环计数器的时候应该时刻注意精度。

当使用foreach循环来迭代输出数组元素或集合时,系统将数组元素,集合元素的副本传给循环计数器——即foreach循环中的循环计数器并不是数组元素,集合元素本身。

instanceof运算符前面操作数的编译时类型必须是如下3种情况:
1.要么与后面的类相同。
2.要么是后面类的父类。
3.要么是后面类的子类。
instanceof运算返回的结果与前一个操作数(引用变量)实际引用的对象的类型有关,如果它实际引用的对象是第二个操作数的实例,或者是第二个操作数的子类,实现类的实例,instanceof运算的结果返回true,否则返回false。

在编译阶段,强制转型要求被转型变量的编译时类型必须是如下3种情况之一:
1.被转型变量的编译时类型与目标类型相同。
2.被转型变量的编译时类型是目标类型的父类。
3.被转型变量的编译时类型是目标类型的子类,这种情况下可以自动向上转型,无需强制转换。
在运行阶段,被转型变量所引用对象的实际类型必须是目标类型的实例,或者是目标类型的子类,实现类的实例,否则在运行时将引发ClassCastException异常。
null调用instanceof运算符时返回false。

为Singleton类提供了readResolve()方法,当JVM反序列化地恢复一个新对象时,系统会自动调用这个readResolve()方法返回指定好的对象,从而保证系统通过反序列化机制不会产生多个java对象。

防止构造器递归调用:
1.尽量不要在定义实例变量时指定实例变量的值为当前类的实例;
2.尽量不要初始化块中创建当前类的实例;
3.尽量不要在构造器内调用本构造器创建Java对象。
总之,如果一个类的实例持有当前类的其他实例时需要特别小心,因为程序很容易形成递归调用。

根据精确匹配的原则,当实际调用时传入的实参同时满足多个方法时,如果某个方法的形参要求参数范围越小,这个方法就越精确。

非静态内部类不可能有无参数的构造器----即使系统为非静态内部类提供一个默认的构造器,这个默认的构造器也需要一个外部类形参。系统在编译阶段总会为非静态内部类的构造器增加一个参数,非静态内部类的构造器的第一个形参总是外部类。非静态内部类不允许拥有静态成员。静态内部类增不能访问外部类的非静态成员。

实现native方法:
1.用javah编译生成的class文件,将产生一个.h文件。
2.写一个.cpp文件实现native方法,其中需要包含第一步产生的.h文件(.h文件中又包含了JDK带的jni.h文件)。
3.将第二步的.cpp文件编译成动态链接库文件。
4.在Java中庸System的loadLibrary()方法或Runtime的loadLibrary()方法加载第三步产生的动态链接库文件,就可以在Java程序中调用这个native()方法了。

资源关闭主要保证如下3点:
1.使用finally块关闭物理资源,保证关闭操作总会被执行。
2.关闭每个资源之前首先保证引用该资源的引用变量不为null。
3.为每个物理资源使用单独try……catch块关闭资源,保证关闭资源时引发的异常不会影响其他资源的关闭。

当System.exit(0)被调用时,虚拟机退出前要执行两项清理工作:
1.执行系统中注册的所有关闭钩子;
2.如果程序调用了System.runFinalizerOnExit(true);,那么JVM会对所有还未结束的对象调用Finalizer。
第二种方式已经被证明是极度危险,因此JDK API文档中说明第二个方式已经过时了,因此实际开发中不应该使用这种危险行为。
第一种方式则是一种安全的操作,程序可以将关闭资源的操作注册成为关闭钩子。在JVM退出之前,这些关闭钩子将会被调用,从而保证物理资源被正常关闭。Runtime.getRuntime().addShutdownHook(new  Thread(){});

当Java程序执行try块,catch块时遇到了return语句,return语句会导致该方法立即结束。系统执行完return语句之后,并不会立即结束该方法,而是去寻找该异常处理流程中是否包含finally块,如果没有finally块,方法终止,返回相应的返回值。如果有finally块,系统立即开始执行finally块——只有当finally块执行完成后,系统才会再次跳回来根据return语句结束方法,如果finally块里使用了return语句来导致方法结束,则finally块已经结束了方法,系统将不会跳回去执行跳回去执行try块,catch块里的任何代码。

不要在程序中过度使用异常机制,千万不要使用异常处理机制来代替流程控制。对于程序中各种能够预知的情况,应该尽量进行处理,不要盲目地使用异常捕获来代替流程控制。

根据Java语言规范,如果一个catch子句试图捕获一个类型为XxxException的Checked异常,那么它对应的try子句必须可能抛出XxxException或其子类的异常,否则编译器将提示该程序具有编译错误——但在所有Checked异常中,Exception是个异类,无论try块是怎样的代码,catch(Exception ex)总是正确的。

继承两个接口,只能抛出异常中的交集,不能声明抛出任何异常。
调用方法时传入的实际参数可能被向上转型,通过这种向上转型可以使之符合被调方法的实际需要。

内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节。
在外部类以外的地方来定义内部类(包括静态和非静态两种)变量的语法格式如下
OuterClass.InnerClass varName
在外部类以外的地方创建非静态内部类实例的语法如下:
OuterInstance.new InnerConstructor()
在外部类以外的地方创建静态内部类实例的语法如下:
new OuterClass.InnerConstructor()

局部内部类的class文件的文件名比成员内部类的class文件的文件名多了一个数字,这是因为同一个类里不可能有两个同名的成员内部类,而同一个类里则可能有两个以上同名的局部内部类(处于不同方法中),所以Java为局部内部类的.class文件名中增加了一个数字,用于区别。

匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立刻创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类。
匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块来完成构造器需要完成的事情。

枚举类的实例只能是枚举值,而不是随意地通过new来创建枚举类对象。(Enum.valueof(class,String enumname) ).枚举类的构造器只能使用private修饰。

如果不想保留运行Java程序的命令行窗口,执行start XXX命令。
Main-Class:<空格>类名<回车>
(冒号前面是key,冒号后面是value,格式:
1.每行只能定义一个key-value对,每行key-value之前不能有空格,即key-value对必须顶格写。
2.每组key-value之间:(英文冒号后紧跟一个英文空格),少些了冒号或者空格都是错误的。
3.文件开头不能有空行。
4.文件必须以一行空行结束。)
jar cvfm test.jar a.txt test

当使用Iterator来迭代访问Collection集合元素时,Collection集合里的元素不能被改变,只有通过Iterator的remove方法来删除上次next方法返回的几个元素才可以。

如果有两个元素通过equals方法比较返回true,但它们的hashcode()方法返回值不相等,hashset将会把他们储存在不同的位置,也就可以添加成功,简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashcode()方法返回值也相等。

重写hashcode()方法的基本规则:
1.当两个对象通过equals方法比较返回true时,这两个对象的hashcode应该相等。
2.对象中用作equals比较标准的属性,都应该用来计算hashCode值。
计算多个hashCode组合计算出一个hashCode值返回,如果为了避免直接相加产生偶然相等(两个对象的属性并不相等,但它们的和恰好相等),可以通过为各属性乘以任意一个质数后再相加。
当向HashSet中添加可变对象时,必须十分小心,如果修改HashSet集合众的对象,有可能导致该对象与集合中其他对象相等,从而导致HashSet无法准确访问该对象。
LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。

Java的一些常用类已经实现了Comparable接口:
BigDecimal,BigInteger以及所有数值型对应包装类;
Character:按字符的UNICODE值进行比较。
Boolean:true对应的包装类实例大于false对应的包装类实例;
String:按字符串中字符的UNICODE值进行比较;
Date。Time:后面的时间,日期比前面的时间,日期大。

向TreeSet集合中添加元素时,只有第一个元素可以无须实现Comparable接口,后面添加的所有元素必须实现Comparable接口。当然这也不是一种好做法,当试图从TreeSet中取出元素时,依然会引发ClassCastException。
当需要把一个对象放入TreeSet中时,重写该对象对应类的equals()方法时,应保证方法与compareTo(Object obj)方法有一致的结果,其规则是:如果两个对象通过equals方法比较返回true时,这两个对象通过compareTo(Object obj)方法比较应返回0;

一旦改变了TreeSet集合里可变元素的属性。当再试图删除该对象时,TreeSet也会删除失败(甚至集合中原有的,属性没被修改,但与修改后元素相等的元素也无法删除。为了让程序更加健壮,推荐HashSet和TreeSet集合众只放入不可变对象。
当通过Comparator对象来实现TreeSet的定制排序时,依然不可以向TreeSet中添加类型不同的对象,否则依然会引发ClassCastException异常。使用定制排序时,TreeSet对集合元素排序时不管集合元素本身大小,而是由Comparator对象负责集合元素的排序规则。

EnumSet集合不允许加入null元素。如果试图加入null元素,EnumSet将抛出NullPointerException异常。如果仅仅只是试图测试是否出现null元素或删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。
List判断两个对象相等只要通过equals方法比较返回true即可。

ListIterator增加了向前迭代的功能(Iterator只能向后迭代),而且ListIterator还可以通过add方法想List集合中添加元素(Iterator只能删除元素).

如果想ArrayList集合或Vector集合中添加大量元素时,可使用ensureCapacity方法一次性地增加capacity。这可以减小增加重分配的次数,从而提高性能。trimToSize():调整ArrayList或Vector集合的capacity为列表当前大小。程序可调用该方法来减少ArrayList或Vector集合对象储存空间。

Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里的元素,不可增加,删除该集合里的元素。

对于所有内部基于数组的集合实现,例如ArrayList,Vector等,使用随机访问的速度比使用Iterator迭代访问的性能要好,因为随机访问会被映射成队数组元素的访问。

HashMap,Hashtable判断两个value相等的标准通过equals比较返回true即可。

IdentityHashMap要求两个key严格相等时才认为两个key相等。

当TreeMap被填充之后,就可以调用KeySet(),取得由key组成的Set,然后使用toArray()生成key的数组。接下来使用Arrays的binarySearch()方法在已排序的数组中快速地查询对象。

load factor(负载因子) = size/capacity  默认为0.75

Collections提供了对List集合元素排序;
查找,替换集合元素,同步控制(synchronizedXxx),设置不可变集合。(emptyXxx,singletonXxx,unmodifiableXxx)
Enumeration迭代器只能遍历Vector,Hashtable这种古来的集合
(hasMoreElements,nextElement)

当创建带泛型声明的自定义类,为该类定义构造器时,构造器名还是原来的类名,不要增加泛型声明。

泛型对其所有可能的类型参数,都具有同样的行为,从而可以把相同的类当成许多不同的类来处理,与此完全一致的是,类的静态变量和方法也在所有的实例间共享,所以在静态方法,静态初始化或者静态变量的声明和初始化中不允许使用类型形参。
数组和泛型有所不同,假设Foo是Bar的一个子类型(子类或者子接口),那么Foo[]依然是Bar[]的子类型;但G<Foo>不是G<Bar>的子类型。
程序需要为形参设置多个上限(至多有一个父类上限,可以有多个接口上限)表明给类型形参必须是其父类的子类(包括是父类本身也行),并且实现多个上限接口的。

数组元素的类型不能包含类型变量或类型形参,除非是无上限的类型通配符。

在默认情况下,Scanner使用空白(包括空格,Table空白,回车)作为多个输入项之间的分隔符。
与Scanner不同的是,BufferedReader不能读取基本类型输入项,它总是读取String对象。

如果两个Random对象的种子相同,而且方法的调用顺序也相同,则它们会产生相同的数字序列。
使用BigDecimal时,优先使用基于String的构造器。如果必须使用double浮点数作为BigDecimal构造器的参数时,不要直接将该double浮点数作为构造器参数创建BigDecimal对象,而是应该通过BigDecimal.valueOf(double value)静态方法来创建BigDecimal对象。

Calendar有两种解释日历字段的模式:lenient模式和non-lenient模式。当Calendar处于lenient模式时,每个时间字段可接受超出它允许范围的值。当Calendar处于non-lenient模式时,如果为某个时间字段设置的值超出了它允许的取值范围,程序将会抛出异常。

set方法延迟修改,set(f,value)方法将日历字段f更改为value,此外,它还设置了一个内部成员变量,以指示日历字段f已经被更改。

预定义字符\w,\W,\s,\S,.,\d,\D
方括号表达式  枚举,范围-,求否^,与&&,并。
圆括号表达式 或运算符|

Panel和Applet默认使用FlowLayout布局管理器。
Frame,Dialog,ScrollPane默认使用BorderLayout布局管理器。
GridLayout
使用GridBagLayout布局管理器的步骤如下:
1.创建GridBagLayout布局管理器,并指定GUI容器使用该布局管理器
GridBagLayout gb =  new GridBagLayout();
2.创建GridBagConstraints对象,并设置该对象的相关属性(用于设置受该对象控制的GUI组建的大小,跨越性)。
3.调用GridBagLayout对象的方法来建立GridBagConstraints对象和受控制组件之间的关联。
4.添加组件,与采用普通布局管理器添加组件的方法完全一样。
constainer.add(c);
CardLayout

在Java容器中采用绝对定位的步骤:
1.将Container的布局管理器设置null:setLayout(null);
2.往容器上加组件的时候,先调用setBounds()或setSize()方法来先设置组件的大小,位置。
但采用绝对定位可能导致GUI界面失去跨平台特性。

BoxLayout通常和Box容器结合使用。
createHorizontalBox(),createVerticalBox();
间距 createHorizontalGlue(),createVerticalGlue()可在两个方向同时拉伸的间距。
createHorizontalStrut(int width),createVerticalStrut(int width)可在横向,纵向任意一个方向上拉伸的空白组件。
createRigidArea(Dimension d):创建指定宽度,高度的RigidArea。

对话框的构造器可能有如下三个参数:
owner:指定该对话框所依赖的窗口,既可以是窗口,也可以是对话框。
title:指定该对话框的窗口变态标题。
mode:指定该对话框是否有模式。可以是true或false。
Dialog类还有一个子类:FileDialog,而mode用于指定该窗口用于打开文件或保存文件。该参数支持FileDialog.LOAD,FileDialog.SAVE.

低级事件:
1.ComponentEvent:组件事件,当组件尺寸发生变化,位置发生移动,显示/隐藏状态发生改变时候触发事件。
2.ContainerEvent:容器事件,当容器里生成添加组件,删除组件时触发该事件。
WindowEvent:窗口事件,当窗口状态发生改变(如打开,关闭,最大化,最小化)时触发。
FocusEvent:焦点事件,当组件得到焦点或失去焦点时触发该事件。
KeyEvent:键盘事件,当键经行按下,松开,单击时触发该事件。
MouseEvent:鼠标时间,当鼠标经行单击,按下,松开,移动等动作触发该事件。
PaintEvent:组件绘制事件,该事件是一个特殊事件类型,当GUI组件调用update/paint方法来呈现自身时将触发该事件,该事件并非专用于事件处理模型。

高级事件:
1.ActionEvent:动作事件。
2.AdjustmentEvent:调节事件。
3.ItemEvent:选项事件。
4.TextEvent:文本事件。

调用ActionEvent对象的getActionCommand方法,用于获取被单击按钮上的文本。

例如Ctrl+A:
MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A);
如果该快捷键还需要Shift键的辅助,则可使用:
MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A,true);

需要使用菜单分隔符:
1.调用Menu对象的addSeparator方法来添加菜单分隔线。
2.添加new MenuItem("-")菜单项来添加菜单分割线。

PopupMenu对象创建右键菜单步骤:
1.创建PopupMenu的实例。
2.创建多个MenuItem的多个实例,依次将这些实例加入PopupMenu中。
3.将PopupMenu加入到目标组件之中。
4.为需要出现上下文菜单的组件编写鼠标监听器,当用户释放鼠标右键时弹出右键菜单。e.isPopupTrigger()  pop.show(p,e.getX(),e.getY());

repaint方法调用update方法;update方法调用paint方法。
AWT普通组件可以通过Color和Font来改变它的前景色和字体,除此之外,所有组件都有一个setBackground方法用于设置组件的背景色。
Timer(int dalay,ActionListener listener):每隔delay毫秒,系统自动触发ActionListener监听器里面的事件处理器(actionPermed方法);

Clipboard使用方法:
1.创建一个Clipboard实例,既可以创建系统剪贴板,也可以创建本地剪贴板。
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
创建本地剪贴板:
Clipboard clipboard = new Clipboard(String name);
2.将需要放入剪贴板中的字符串封装成对象。比如StringSelection对象。
StringSelection st = new StringSelection(targetStr);
3.调用剪贴板对象的setContents方法将StringSelection放进剪贴板中,该方法需要两个参数,第一个参数是Transferable对象,代表放进剪贴板中对对象;第二个参数是ClipboardOwner对象,该对象代表剪贴板数据的所有者,通常我们无须关心剪贴板数据的所有者。所以把第二个参数设为null。
如 clipboard.setContents(st , null);

从剪贴板中取出数据则比较简单,调用Clipboard对象的getData(DataFlavor flavor)方法即可取出剪贴板中指定格式的内容,如果指定flavor的数据不存在,该方法将引发UnsupportedFlavorException异常,为了避免出现异常,可以先调用Clipboard对象的isDataFlavorAvailable(DataFlavor flavor)来判断指定flavor的数据是否存在。

ResultSet的getString()方法几乎可以获取除Blob之外的任意类型列的值,因为所有数据类型都可以自动转换成字符串。

创建PreparedStatement对象使用Connection的prepareStatement方法,该方法需要传入一个SQL字符串,该SQL字符串可以包含占位符参数。

注意拼接SQL字符串时,字符串必需用单引号引起来。

使用PreparedStatement执行带占位符参数的SQL语句时,SQL语句中的占位符参数只能代替普通值,不要使用占位符参数代替表名,列名等数据库对象。

以默认方式打开的ResultSet是不可更新的,如果希望创建可更新的ResultSet,必须在创建Statement或PreparedStatement时传入额外的参数。Connection在创建Statement或PreparedStatement时还可额外传入两个参数:
1.resultSetType:控制ResultSet的类型,该参数可以是如下三个值:
    一.ResultSet.TYPE_FORWARD_ONLY:该常量控制记录指针只能向前移动,这是JDK 1.4以前的默认值。
    二.ResultSet.TYPE_SCROLL_INSENSITIVE:该常量控制记录指针可以自由移动(可滚动结果集),但底层数据的改变不会影响ResultSet的内容。
    三.Result.TYPE_SCROLL_SENSITIVE:该常量控制记录指针可以自由移动(可滚动结果集),而且底层数据的改变会影响ResultSet的内容。
2.resultSetConcurrency:控制ResultSet的并发类型,该参数可以接受如下两个值:
    一.ResultSet.CONCUR_READ_ONLY:该常量指示ResultSet是只读的并发模式(默认)。
    二.ResultSet.CONCUR_UPDATABLE:该常量指示ResultSet是可更新的并发模式。

如果要创建可更新的结果集,查询语句查询的数据通常只能来自于一个数据表,而且查询结果中的数据列必须包含主键列,否则将会引起更新失败。

虽然ResultSetMetaData可以准确分析出ResultSet里包含多少列以及每列的列名,数据类型等,但使用ResultSetMetaData需要一定的系统开销,因此如果编程过程中已经知道ResultSet里包含多少列,每列的列名,类型等信息,就没有必须使用ResultSetMetaData来分析该ResultSet对象了。

当事务包含的全部数据库操作都成功执行后,应该提交(commit)事务,使这些修改永久生效,事务提交有两种方式:显式提交和自动提交
使用commit,执行ddl或dcl,或者程序正常退出。
当事务所包含的任意一个数据库操作执行失败后,应该回滚(rollback)事务,使该事务中所作的修改全部失效。事务回滚有两种方式:显式回滚和自动回滚。使用rollback,系统错误或者强行退出。

conn.setAutoCommit(false);  //关闭自动提交,开启事务。
程序中还可调用Connection提供的getAutoCommit方法来获取该连接的自动提交模式。
conn,commit(); //提交事务。
conn.rollback(); //回滚事务。
实际上当Connection遇到一个未处理的SQLException异常时,系统将会非正常退出,系统会自动回滚该事务,但如果程序显式捕获了该异常,则需要在异常处理块中显式回滚事务。
savepoint 对象。

批量更新必须得到底层数据库的支持,可以通过调用DatabaseMetaData的supportsBatchUpdates方法来查看底层数据库是否支持批量更新。
如果在批量更新的addBatch方法中添加了select查询语句,程序将直接出现错误。
JDBC提供了DatabaseMetaData来封装数据库连接对应数据库的信息,通过Connection提供的getMetaData()方法就可以获取到数据库对应的DatabaseMetaData对象。很多DatabaseMetaData方法都需要传入一个xxxPattern的模式字符串,这里的xxxPattern不是正则表达式,而是SQL里的模式字符串,即用百分号(%)代表任意多个字符,使用下划线(_)代表一个字符。通常情况下,如果把该模式字符串参数设置为null,即表明该参数不作为过滤条件。

DBCP数据源:
C3P0数据源:可自动清理不再使用的Connection,还可以自动清理Statement和ResultSet;

InputStream和Reader还支持如下几个方法来移动记录指针:
void mark(int readAheadLimit):在记录指针当前记录一个标记(mark);
boolean markSupported():判断此输入流是否支持mark()操作,既是否支持记录标记。
void reset():将此流的记录指针重新定位到上一次记录标记(mark)的位置
long skip(long n):记录指针向前移动n一个字节/字符。

使用Java的IO流执行输出时,不要忘记了关闭输出流,关闭输出流除了可以保证流的物理资源被回收之外,可能还可以将输出流缓冲中的数据flush到物理节点里(相当于在执行close方法之前,自动执行输出流的flush()方法);程序只要正常关闭所有输出流即可保证程序正常。

由于PrintStream类的输出功能非常强大,通常如果我们需要输出文本内容,都应该将输出流包装成PrintStream后经行输出。
由于BufferedReader具有一个readline方法,可以非常方便地一次读入一行内容,所以经常把读取文本内容的输入流包装成BufferedReader,用以方便地读取输入流的文本内容。

当我们使用处理流来包装底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的处理流即可。关闭最上层的输出流时,系统会自动关闭被该处理流包装的节点流。

通常有一个规则:如果需要经行输入/输出的内容是文本内容,则应该考虑使用字符流,如果需要进行输入/输出的二进制内容,则应该考虑使用字节流。

增加缓冲功能后一定要使用flush()才能将缓冲区的内容写入实际的物理节点。

RandomAccessFile依然不能向文件的指定位置插入内容,如果直接将文件记录指针移动到中间某位置后开始输出,则新输出的内容覆盖文件中原有的内容。如果需要向指定位置插入内容,呈现需要先把插入点后面内容读入缓冲区,等把需要插入的数据写入文件后,再将缓冲区的内容追加到文件后面。

Java序列化机制采用序列化算法:
1.所有保存到磁盘中的对象都有一个序列化编号。
2.当丞相试图序列化一个对象时,程序将先检查该对象是否已经被序列化过,只有当该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列并输出。
3.如果某个对象是已经序列化过的,程序将直接只是输出一个序列化编号,而不是再次重新序列化该对象。

当使用Java序列化机制序列化可变对象时,只有当第一次调用writeObject方法来输出对象时才会将对象转换成字节序列,并写出到ObjectOutStream;在后面程序中如果该序列已经存在,系统不再转换。

buffer :capacity,limit,position,rewind,flip,clear。
Channel:map,read和write。

所有的Channel都不应该通过构造器来直接创建,而是通过传统的节点InputStream,outputStream的getChannel方法来返回对应的Channel。

常用字符串别名:
1.GBK:简体中文字符集。
2.BIG5:繁体中文字符集。
3.ISO-8859-1:拉丁字母表NO.1,也叫做ISO-LATIN-1.
4.UTF-8:8位UCS转换格式。

forname()..获得了Charset对象之后就可以通过该对象的newDecoder(),newEncoder()这两个方法分别返回CharsetDecoder和CharsetEncoder对象,代表Charset的解码器和编码器,调用CharsetDecoder的decode方法就可以将ByteBuffer转换成CharBuffer,调用CharsetEncoder的encode方法就可以将CharBuffer或String转换成ByteBuffer。
在String类里也提供了一个getBytes(String charset)方法,该方法返回byte[],该方法也是使用指定的字符集将字符串转换成字节序列。
lock和trylock方法存在区别:当lock试图锁定某个文件时,如果无法得到文件锁,程序将一直堵塞。二tryLock也是尝试锁定文件,它将直接返回而不是堵塞,如果获得了文件锁,该方法返回该文件锁,否则将返回null。

关于文件锁还有如下几点:
1.在某些平台上,文件锁仅仅是建议性的,并不是强制性的,这意味着即使一个程序不能获得文件锁,它也可以对该文件进行读写。
2.在某些平台上,不能同步地锁定一个文件并把它映射到内存中。
3.文件锁是由Java虚拟机所持有的,如果两个Java程序使用同一个Java虚拟机运行,则它们不能对同一个文件进行加锁。
4.在某些平台上当关闭FileChannel时,会释放Java虚拟机在该文件上的所有锁,因此应该避免对同一个被锁定的文件打开多个FileChannel。

并发性(concurrency)和并行性(parallel)是两个概念。并发指在同一时刻,有多条指令在多个处理器上同时执行;并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值