/** * @author 继承Thread类,直接调用run方法 * */ class hello extends Thread { private String name; public hello() { } public hello(String name) { this.name = name; } public void run() { System.out.println(name + "运行"); } public static void main(String[] args) { Thread h1=new hello("A"); Thread h2=new hello("B"); h1.start();//注意是start方法启动,而不是run h2.start(); } }
/** * @author 实现Runnable接口 * */ class hello implements Runnable { private String name; public hello() { } public hello(String name) { this.name = name; } public void run() { System.out.println(name + "运行"); } public static void main(String[] args) { Thread h1=new Thread(new hello("A"));//注意是代理模式 Thread h2=new Thread(new hello("B")); h1.start(); h2.start(); } }
其实Thread也是实现Runnable接口的。
/** * @author 继承Thread类,不能资源共享 * */ class hello extends Thread { private int count = 5; public void run() { System.out.println("count= " + count--); } public static void main(String[] args) { hello h1 = new hello();//主要是因为这里的原因,单独的建立了一个线程 hello h2 = new hello(); hello h3 = new hello(); h1.start(); h2.start(); h3.start(); } }
在上述程序中,每个线程都会输出5,而不会有线程输出4
class hello implements Runnable{ private int ticket = 100; //100张票 public void run() { while(true){ if (this.ticket > 0) { System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--); try { Thread.sleep(1000);//线程休眠 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else{ break; } } } public static void main(String [] args) { hello my = new hello(); new Thread(my, "1号窗口").start(); new Thread(my, "2号窗口").start(); new Thread(my, "3号窗口").start(); } }
由于这里new Thread(my,),故可以共享。实际上与Runnable还是extends无关,可能Runnable更适合这么写。
java.util.concurrent.Executors类的API提供大量创建连接池的静态方法:
newSingleThreadExecutor:
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
newFixedThreadPool:
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
newCachedThreadPool:
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
newScheduledThreadPool:
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
newSingleThreadExecutor:
创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
package BackStage; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class JavaThreadPool { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThreadPool(2); // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口 Thread t1 = new MyThread(); Thread t2 = new MyThread(); Thread t3 = new MyThread(); Thread t4 = new MyThread(); Thread t5 = new MyThread(); // 将线程放入池中进行执行 pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); // 关闭线程池 pool.shutdown(); } } class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName() + "正在执行。。。"); } }
//创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。 ExecutorService pool = Executors.newSingleThreadExecutor();
Gson是Google的一个开源项目,可以将Java对象转换成JSON,也可能将JSON转换成Java对象。Gson里最重要的对象有2个Gson 和GsonBuilder。
注意使用Gson时记得添加第三方类库gson-1.6.jar:
import com.google.gson.Gson;Gson有2个最基本的方法:
1) toJson() – 转换java 对象到JSON
2) fromJson() – 转换JSON到java对象
class TestObjectToJson { private int data1 = 100; private String data2 = "hello"; } TestObjectToJson obj = new TestObjectToJson(); Gson gson = new Gson(); String json = gson.toJson(obj);
import com.google.gson.Gson; class TestJsonFromObject { private int data1; private String data2; } String json = "{'data1':100,'data2':'hello'}"; Gson gson = new Gson(); TestJsonFromObject obj = gson.fromJson(json, TestJsonFromObject.class);
import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; public class TestGson { @SerializedName("FirstField") private String field1; private String secondField; public TestGson(String param1, String param2) { field1 = param1; secondField = param2; } } TestGson obj = new TestGson("aaaa", "bbbbb"); Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create(); gson.toJson(obj);输出结果 {"FirstField":"aaaa","SecondField":"bbbbb"}
//以下只有@Expose的才会选择 import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class TestGson { @Expose private String field1; private String secondField; public TestGson(String param1, String param2) { field1 = param1; secondField = param2; } } TestGson obj = new TestGson("aaaa", "bbbbb"); Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create(); gson.toJson(obj);输出结果:
{ "field1": "aaaa" }
Java 串行化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的串行化机制是RMI、EJB等技术的技术基础。用途:利用对象的串行化实现保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现Serializable接口,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
(1)如果某个类能够被串行化,其子类也可以被串行化。如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可串行化接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可串行化接口,则该类的父类所有的字段属性将不会串行化。
(2)声明为static和transient类型的成员数据不能被串行化。因为static代表类的状态, transient代表对象的临时数据;
(3)相关的类和接口:在java.io包中提供的涉及对象的串行化的类与接口有ObjectOutput接口、ObjectOutputStream类、ObjectInput接口、ObjectInputStream类。
import java.io.*; public class Cat implements Serializable { private String name; public Cat() { this.name = "Cat A"; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Cat cat = new Cat(); try { FileOutputStream fos = new FileOutputStream("catDemo.out"); ObjectOutputStream oos = new ObjectOutputStream(fos); System.out.println(" 1> " + cat.getName()); cat.setName("Cat B"); oos.writeObject(cat); oos.close(); } catch (Exception ex) { ex.printStackTrace(); } try { FileInputStream fis = new FileInputStream("catDemo.out"); ObjectInputStream ois = new ObjectInputStream(fis); cat = (Cat) ois.readObject(); System.out.println(" 2> " + cat.getName()); ois.close(); } catch (Exception ex) { ex.printStackTrace(); } } }// writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的。所以对象能一个一个接连不断的传过来
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
一般机制是java知道类的定义(比如import了这个类,或者就在同一个包里),然后根据类定义去new一个实例出来。
反射机制是不知道类是什么样的,根据字符串之类的类名字等去获取一个实例,然后根据方法名字去执行方法。
好比说,一般情况下画一只老虎,我得先知道老虎长什么样子才能画出来;有了反射机制,我只要知道“老虎”这个名字就能画出来。
类中有什么信息,它就可以获得什么信息。
5.2.1 获得对应的类对象
首先得根据传入的类的全名来创建Class对象(第一步是获得你想操作的类的 java.lang.Class 对象):
方法一:Class c = Class.forName("java.lang.String"); //这条语句得到一个 String 类的类对象。 方法二:Class c = int.class; //可获得基本类型的类信息。 方法三:Class c = Integer.TYPE; //可获得基本类型的类信息。
Class是运行中的class类,forName(className)是将这个名为className的类装入JVM,这样就可以动态的加载类,通过Class的反射机制可以获得此类的一些信息。Class.forName 的作用动态加载和创建Class 对象。
类加载器是用来加载.class文件,读取.class文件的字节码并加载到内存中。
5.2.2 其次创建对象实例:
Class c=Class.forName("className");//注明:className必须为全名,比如,cn.netjava.pojo.UserInfo; Object obj=c.newInstance();//创建对象的实例
5.2.3 再次获得各类信息:
获得构造函数的方法:
Constructor getConstructor(Class[] params)//根据指定参数获得public构造器 Constructor[] getConstructors()//获得public的所有构造器 Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器 Constructor[] getDeclaredConstructors()//获得public的所有构造器获得类方法的方法:
Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法 Method[] getMethods()//获得所有的public方法 Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法 Method[] getDeclaredMethods()//获得所以的public和非public方法
获得类中属性的方法:
Field getField(String name)//根据变量名得到相应的public变量 Field[] getFields()//获得类中所以public的方法 Field getDeclaredField(String name)//根据方法名获得public和非public变量 Field[] getDeclaredFields()//获得类中所有的public和非public方法
http://www.jz123.cn/text/1821910.html
程序中的异常,一般称为例外情况,可以理解为是非正常情况。这里需要分清楚的是异常和错误不是一个概念。异常并非是真正的错误,因为他们是一些例外情况,这些情况有可能不会导致系统直接崩溃掉,但是它的存在只能说是程序的某种缺陷,或者说是非必然缺陷,而Java里面提供的异常体系结构就是为了解决这些缺陷而存在的。
在异常处理机制诞生之前,传统的异常处理方式多数是为了采用返回值来标识程序出现异常的情况,这种方式都很熟悉,如同在调试过程即是有良好的调试工具,但是常用的手段就是System.out.println的方式,但是这样的方式隐含一定的缺点:
[1]一个API可以返回任意的值,但是这些返回值本身不能解释返回值是否代表一个异常发生了,也不能描述异常的详细情况,若要知道该API出现异常的一些内容,还需要调用它的某些方法;在开发过程中,当一个程序本身抛出了异常过后,程序会从程序导致异常的地方跳出来,在java语言里面,使用try和catch块来实现,当JVM碰到这个语句块的时候,它会监听整个Java程序,一旦出现了任何异常情况,它会将整个程序的执行权交给catch块来执行。
Throwable是所有异常的基类,程序中一般不会直接抛出Throwable对象,Throwable本身存在两个子类实例,一个是Error、一个是Exception;
[1]Error:在Java里面Error表示程序在运行期间出现了十分严重的问题以及不可以恢复的错误,这种情况唯一的办法是中止程序运行,JVM一般不会检查Error是否被处理,而本身在程序中也不能捕获Error类型的异常,因为Error一旦产生,该程序基本会处于需要中止的状态。
[2]Exception:在Java里面Exception指的就是在编程过程可能会遇到的异常的概念,也属于Java程序里面允许出现的例外的状况,而Exception本身分为以下两种:
RuntimeException:该异常继承于Exception类,这种类型的异常可以这样理解,为不可估计的异常,一般称为运行时异常,从字面意思上讲就是在程序正式运行的时候会碰到的偶发性异常,这种异常因为是在运行时抛出一般情况下不需要进行捕获操作。
CheckedException:该类异常不存在继承于Exception类的说法,因为Java里面没有CheckedException异常类,而之所以这样区分,因为CheckedException类的异常是在编程过程中经常会遇到的异常,可以翻译为“可检测异常”或者“捕获型异常”,该类异常往往属于编译期异常,一般开发过程会针对系统进行CheckedException的设计。
http://book.51cto.com/art/201009/227779.htm 这篇很有意思
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。
2,或许你已经有了一个用其他语言写成的库或程序,而你希望在java程序中使用它。
3,你可能需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的java程序中调用这些功能。
HelloWorld.java:
class HelloWorld { public native void displayHelloWorld();// 所有native关键词修饰的都是对本地的声明 static { System.loadLibrary("hello");// 载入本地库 } public static void main(String args[]) { new HelloWorld().displayHelloWorld(); } }声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明该方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。 Load动态库:System.loadLibrary("hello");加载动态库(我们可以这样理解:我们的方法 displayHelloWorld()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“hello”是动态库的名字。
2,使用javac命令编译所编写的java类
javac HelloWorld.java
3,使用“javah -jni java类名”生成扩展名为.h的头文件
javah -jni HelloWorld
生成了HelloWorld.h文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: displayHelloWorld * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif这 里我们可以这样理解:这个h文件相当于我们在java里面的接口,这里声明了一个Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致。
实现和由javah命令生成的头文件里面声明的方法名相同的方法。
HelloWorldImpl.c
#include "jni.h" #include "HelloWorld.h" //#include other headers JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) { printf("Hello world!\n"); return; }注意第1行,需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、 jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloWorld.h头文件引入(我是这么理解的:相当于我们在编写java程序的时候,实现一个接口的话需要声明才可以,这里就是将HelloWorld.h头文件里面声明的方法加以实现。当然不一定是这样)。然后保存为 HelloWorldImpl.c就ok了。
5,将C/C++编写的文件生成动态连接库
注意我们这里include了 jni.h和刚才得到的HelloWorld.h文件。因此你要在VC++里面设置好,jni.h在JAVA_HOME/include里面。编译通过后再生成hello.dll文件。
6,运行程序 java HelloWorld
HelloWorld
“CSV”,是Comma Separated Value(逗号分隔值)。因此要存储为csv格式,可用逗号分隔即可。
public class test { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub String string = "aaa,bbb,ccc\nddd,eee,fff"; FileWriter fw = new FileWriter("1.csv"); fw.write(string); fw.close(); } }文本结果为:
aaa,bbb,ccc ddd,eee,fff用excel打开为:
import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.ietf.jgss.Oid; import org.omg.CORBA.PUBLIC_MEMBER; /** * map遍历的三种办法 * * @author us * */ public class test2 { /** * 1.把值放到一个集合里,然后遍历集合 */ public static void f1(Map<String, String> map) { Collection c = map.values(); Iterator it = c.iterator(); for (; it.hasNext();) { System.out.println(it.next()); } } /** * 2.把key放到一个集合里,遍历key值同时根据key得到值 (推荐) */ public static void f2(Map<String, String> map) { Set set = map.keySet(); Iterator it = set.iterator(); while (it.hasNext()) { String s = (String) it.next(); System.out.println(map.get(s)); } } /** * 3.把一个map对象放到放到entry里,然后根据entry同时得到key和值 */ public static void f3(Map<String, String> map) { Set set = map.entrySet(); Iterator it = set.iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = (Entry<String, String>) it.next(); System.out.println(entry.getKey() + ":" + entry.getValue()); } } public static void main(String[] args) { /** * new一个map,然后添加内容 */ Map map = new HashMap(); for (int i = 0; i < 10; i++) { map.put(i + "", i + ""); System.out.println("添加" + i + "成功"); } System.out.println("map大小" + map.size()); f3(map); } }
更简单的写f3():
public static void f3(Map<String, String> map) { for(Map.Entry<String, String> entry:map.entrySet()) System.out.println(entry.getKey() + ":" + entry.getValue()); }
GUID是一个128位长的数字,一般用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义上)3240年不重复。
UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。由以下几部分的组合:当前日期和时间(UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同),时钟序列,全局唯一的IEEE机器识别号(如果有网卡,从网卡获得,没有网卡以其他方式获得),UUID的唯一缺陷在于生成的结果串会比较长。
UUID是由一个十六位的数字组成,表现出来的形式例如:550E8400-E29B-11D4-A716-446655440000
import java.util.UUID; UUID uuid = UUID.randomUUID(); String s = uuid.toString();//用来生成数据库的主键id非常不错
防止多线程,虽然几乎不可能,在纳秒级时间:
import java.io.Serializable; import java.util.UUID; public class Sequence implements Serializable { public static String GeneralID() { synchronized(Sequence.lock){//防止多线程 return UUID.randomUUID().toString().replaceAll("-", "_"); } } public static String lock=new String(); public static void main(String args[]){ System.out.println(GeneralID()); } }
MD5的全称是Message-Digest Algorithm 5,Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。MD5将任意长度的"字节串"变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
算法摘自网络:
package com.hemes.md5; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5 { public String md5Set(String plainText) { String str=""; try { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(plainText.getBytes()); byte b[] = md.digest(); int i; StringBuffer buf = new StringBuffer(""); for (int offset = 0; offset < b.length; offset++) { i = b[offset]; if (i < 0) i += 256; if (i < 16) buf.append("0"); buf.append(Integer.toHexString(i)); } str = buf.toString(); // System.out.println("result: " + buf.toString());// 32位的加密 // System.out.println("result: " + buf.toString().substring(8, 24));// 16位的加密 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return str; } public static void main(String[] args) { MD5 md5=new MD5(); String str=md5.md5Set("123"); System.out.println(str); } }
import java.util.HashMap; import java.util.Map; public class Parser { //将表达式exp解析为ASTNode private ASTNode parserWhere(String exp){ if(exp==null || exp.isEmpty()) return null; //先判断Cache中是否存在 String md5=MD5.md5(exp); ASTNode node=getCacheNode(md5); if(node!=null) return node; //Cache中不存在,再将exp解析为ASTNode ParseDriver pd = new ParseDriver(); node = pd.parseWhere(exp); //将ASTNode加入Cache中 putCache(md5,node); return node; } //以下为本类内建的一个Cache,一个Map(key=MD5值,value=ASTNode) private static Map<String,ASTNode> parserCache; public static void putCache(String key,ASTNode node){ if(parserCache==null) parserCache=new HashMap<String,ASTNode>(); parserCache.put(key, node); } public static ASTNode getCacheNode(String key){ if(parserCache==null) return null; if(parserCache.containsKey(key)) return parserCache.get(key); return null; } }
HiveParser.java
public class HiveParser{ public static final int TOK_FUNCTIONDI=22; public static final int LSQUARE=452; public static final int TOK_PRIV_SHOW_DATABASE=222; public static final int KW_REPAIR=357; public static final int KW_FORMAT=363; }
TokCache.java
static语句块在运行时加载该类后被执行。
import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class TokCache { //使用Java反射机制,根据HiveParser.class载入TOK类型与值的映射 public static Map<String,Integer> tokTypeCache; static{ tokTypeCache=new HashMap<String,Integer>(); for(Field f:HiveParser.class.getDeclaredFields()){ if(f.getType().equals(int.class)) { try { tokTypeCache.put("HiveParser."+f.getName(), f.getInt(null)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } public static int getTokTypeValue(String tokName){ if(tokTypeCache.containsKey(tokName)){ return tokTypeCache.get(tokName); } else{ return -1; } } public static void main(String args[]){ System.out.println(TokCache.getTokTypeValue("HiveParser.KW_IN")); System.out.println(TokCache.getTokTypeValue("HiveParser.KW_FORMAT")); } }
1,commons-logging.jar:只是提供了对外的统一接口,真正的记录日志的工具是log4j或者sun logger。apache的common-logging包是通用日志接口,通过这个中间层,你可以随便指定到底用哪个日志系统。
2,log4j.rar:真正的实现部分,Log4j是Apache的一个开放源代码项目,需要一个配置文件:在CLASSPATH下建立log4j.properties
3,log4j.properties:其内容可以设置日志输出级别,从高到低是:Debug Info Warn Error Fatal,该文件可如下设置
log4j.rootLogger=INFO,console #log4j.rootLogger=warn,error,fatal log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.Encoding=UTF-8 log4j.appender.console.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH:mm:ss}] [ Class = %C | Method = %M | Line = %L ] | %m |%n log4j.logger.info=info log4j.appender.info=org.apache.log4j.DailyRollingFileAppender log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH:mm:ss}] [ Class = %C | Method = %M | Line = %L ] | %m |%n log4j.appender.info.datePattern='.'yyyy-MM-dd log4j.appender.info.Threshold=INFO log4j.appender.info.append=true log4j.appender.info.Encoding=UTF-8 log4j.appender.info.File=${loghome}/info.log log4j.logger.debug=debug log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender log4j.appender.debug.layout=org.apache.log4j.PatternLayout log4j.appender.debug.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH:mm:ss}] [ Class = %C | Method = %M | Line = %L ] | %m |%n log4j.appender.debug.datePattern='.'yyyy-MM-dd log4j.appender.debug.Threshold=DEBUG log4j.appender.debug.append=true log4j.appender.debug.Encoding=UTF-8 log4j.appender.debug.File=${loghome}/debug.log log4j.logger.warn=warn log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender log4j.appender.warn.layout=org.apache.log4j.PatternLayout log4j.appender.warn.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH:mm:ss}] [ Class = %C | Method = %M | Line = %L ] | %m |%n log4j.appender.warn.datePattern='.'yyyy-MM-dd log4j.appender.warn.Threshold=WARN log4j.appender.warn.append=true log4j.appender.warn.Encoding=UTF-8 log4j.appender.warn.File=${loghome}/warn.log log4j.logger.fatal=fatal log4j.appender.fatal=org.apache.log4j.DailyRollingFileAppender log4j.appender.fatal.layout=org.apache.log4j.PatternLayout log4j.appender.fatal.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}] [ Class \= %C | Method \= %M | Line \= %L ] | %m |%n log4j.appender.fatal.datePattern='.'yyyy-MM-dd log4j.appender.fatal.Threshold=FATAL log4j.appender.fatal.append=true log4j.appender.fatal.Encoding=UTF-8 log4j.appender.fatal.File=${loghome}/fatal.log #The log output to the directory loghome=/tmp/log
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Test { private static Log logger=LogFactory.getLog(Test.class); public static void main(String[] args) { logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); } }
有时候对于一个对象,需要设置一个布尔型的属性,来表示某些特性,但是用如下方法,默认值为false:
public class Apple{ private boolean isRed; public static void main(String[] args) { Apple test = new Apple(); } }这肯定不是希望得到的结果,因为无法区分是赋值后的false,还是根本没有赋值呢,所以应该将
private boolean isRed;改用:
private Boolean isRed;这样默认值时null,当为null时,就表示未赋值。
//一个Java文件可以有多个类,但public权限的类最多只能有一个,若有则文件名必须是public类名同名 public class Car { private Engine engine ; } //不能是public了,同包中仍可访问 class Engine{ }
//Car类中有内部类Engine,外部不能访问 public class Car { private Engine engine ; //内部类 class Engine{ } }
对于获取资源文件,一般,如要取得c:/test.txt文件,就会这样用File file = new File("c:/test.txt");但缺点是资源硬编码(即直接使用绝对路径)。更好的方法是:Class.getResource()与Class.getResourceAsStream()方法,以下详细解释之。比如我们有以下目录:
|--project |--src |--javaapplication |--Test.java |--file1.txt |--file2.txt |--build |--javaapplication |--Test.class |--file3.txt |--file4.txt
file3.txt: 方法一:File file3 = new File(Test.class.getResource("file3.txt").getFile()); 方法二:File file3 = new File(Test.class.getResource("/javaapplication/file3.txt").getFile()); 方法三:File file3 = new File(Test.class.getClassLoader().getResource("javaapplication/file3.txt").getFile());
file4.txt: 方法一:File file4 = new File(Test.class.getResource("/file4.txt").getFile()); 方法二:File file4 = new File(Test.class.getClassLoader().getResource("file4.txt").getFile());
file1.txt 方法一:File file1 = new File("c:/project/src/javaapplication/file1.txt");
file2.txt 方法一:File file2 = new File("c:/project/src/file2.txt");
http://blog.csdn.net/mcpang/article/details/7024685
package com; public class MD5Test { /** * @param args */ public static void main(String[] args) { System.out.println(decrypt("137%128%143%145%124%144%135%143%76%")); System.out.println(encrypt("frontdev")); } /** *用户名解密 *@param ssoToken 字符串 *@return String 返回加密字符串 */ public static String decrypt(String ssoToken) { try { String name = new String(); java.util.StringTokenizer st=new java.util.StringTokenizer(ssoToken,"%"); while (st.hasMoreElements()) { int asc = Integer.parseInt((String)st.nextElement()) - 27; name = name + (char)asc; } return name; }catch(Exception e) { e.printStackTrace() ; return null; } } /** *用户名加密 *@param ssoToken 字符串 *@return String 返回加密字符串 */ public static String encrypt(String ssoToken) { try { byte[] _ssoToken = ssoToken.getBytes("ISO-8859-1"); String name = new String(); // char[] _ssoToken = ssoToken.toCharArray(); for (int i = 0; i < _ssoToken.length; i++) { int asc = _ssoToken[i]; _ssoToken[i] = (byte) (asc + 27); name = name + (asc + 27) + "%"; } return name; }catch(Exception e) { e.printStackTrace() ; return null; } } }
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class ObjectPersistence { //将对象obj持久化到文件fileName中 public static void output(Object obj, String fileName) { try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream(fileName)); out.writeObject(obj); out.close(); } catch (Exception ex) { ex.printStackTrace(); } } //从资源文件fileName中获取对象 public static Object inputFromResource(String fileName) { try { InputStream is=ObjectPersistence.class.getResourceAsStream(fileName); ObjectInputStream in = new ObjectInputStream(is); Object obj = in.readObject(); in.close(); return obj; } catch (Exception ex) { ex.printStackTrace(); return null; } } //从文件fileName中获取对象 public static Object input(String fileName) { try { ObjectInputStream in = new ObjectInputStream(new FileInputStream( fileName)); Object obj = in.readObject(); in.close(); return obj; } catch (Exception ex) { ex.printStackTrace(); return null; } } }
Configuration.java
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 1,配置文件存放在本classpath的根下/ * 2,使用单例模式:Configuration.getInstance() * 3,每次set操作,都会在该配置文件中save操纵(持久化) */ public class Configuration { static Log logger = LogFactory.getLog(Configuration.class); private Properties pro; private static Configuration instance; private static String configFile; public Configuration() { } public static Configuration getInstance(){ try{ if(instance!=null) return instance; if(configFile==null) configFile = "/app_config.property"; instance=new Configuration(configFile); } catch(Exception ex){ logger.error(ex); instance=new Configuration(); } return instance; } //单例模式,构造函数为私有的 private Configuration(String filePath) { pro = new Properties(); try { // 读取属性文件 InputStream inputFile = Configuration.class.getResourceAsStream(filePath); pro.load(inputFile); inputFile.close(); } catch (Exception e) { logger.error("读取属性文件--->失败!- 原因:文件路径错误或者文件不存在", e); } } public String getValue(String key) { if (pro == null) return null; if (pro.containsKey(key)) { String value = pro.getProperty(key); return value; } else { return ""; } } public void clear() { if (pro == null) return; pro.clear(); save(); } public void setValue(String key, String value) { if (pro == null) return; pro.setProperty(key, value); save(); } //设置为私有 private void save() { if (pro == null) return; try { //获取当前所在的根位置 String currentPath = Configuration.class.getClass().getResource("/").getPath(); FileOutputStream outputFile = new FileOutputStream(currentPath+configFile); System.out.println("持久化为:"+pro.toString()); pro.store(outputFile,""); outputFile.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException ioe) { ioe.printStackTrace(); } } public static void main(String[] args){ //使用方法,单例使用getInstance Configuration configuration = Configuration.getInstance(); System.out.println(configuration.getValue("sex")); configuration.setValue("name","dudu"); System.out.println(configuration.getValue("name")); configuration.clear(); } }