4、查看版本号和当前日?
mysql> select version(),current_date();
+----------------+-----------------+
| version() | current_date() |
+----------------+-----------------+
| 3.23.25a-debug | 2001-05-17 |
+----------------+-----------------+
1 row in set (0.01 sec)
mysql>
此命令要求mysql服务器告诉你它的版本号和当前日期。尝试用不同大小写操作上q命令,看结果如何。结果说明mysql命o的大写l果是一致的?
注意中间的逗号和最后的分号的用方法?/p>
4、一行多命o
输入如下命oQ?
mysql> SELECT USER(); SELECT NOW();
+------------------+
| USER() |
+------------------+
| ODBC@localhost |
+------------------+
1 row in set (0.00 sec)
+---------------------+
| NOW() |
+---------------------+
| 2001-05-17 23:06:15 |
+---------------------+
1 row in set (0.00 sec)
mysql>
注意中间的分P命o之间用分号隔开?
MySQL对于字符集的指定可以l化C个数据库Q一张表Q一列,应该用什么字W集?/p>
但是Q传l的 E序在创建数据库和数据表时ƈ没有使用那么复杂的配|,它们用的是默认的配置Q那么,默认的配|从何而来呢?
(1)~译MySQL Ӟ指定了一个默认的字符集,q个字符集是 latin1Q?br /> (2)安装MySQL Ӟ可以在配|文?(my.ini) 中指定一个默认的的字W集Q如果没指定Q这个值承自~译时指定的Q?br /> (3)启动mysqld Ӟ可以在命令行参数中指定一个默认的的字W集Q如果没指定Q这个值承自配置文g中的配置,此时 character_set_server 被设定ؓq个默认的字W集Q?br /> (4)当创Z个新的数据库Ӟ除非明确指定Q这个数据库的字W集被缺省设定ؓcharacter_set_serverQ?br /> (5)当选定了一个数据库Ӟcharacter_set_database 被设定ؓq个数据库默认的字符集;单的ȝ一下,如果什么地斚w不修改,那么所有的数据库的所有表的所有栏位的都用 latin1 存储Q不q我们如果安?MySQLQ一般都会选择多语a支持Q也是_安装E序会自动在配置文g中把 default_character_set 讄?UTF-8Q这保证了缺省情况下Q所有的数据库的所有表的所有栏位的都用 UTF-8 存储?/p>
2.查看默认字符?默认情况下,mysql的字W集是latin1(ISO_8859_1)
通常Q查看系l的字符集和排序方式的设定可以通过下面的两条命令:
mysql> SHOW VARIABLES LIKE 'character%';
+--------------------------+---------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | D:"mysql-5.0.37"share"charsets" |
+--------------------------+---------------------------------+
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
+----------------------+-----------------+
3.修改默认字符?br />
(1) 最单的修改ҎQ就是修改mysql的my.ini文g中的字符集键|
? default-character-set = utf8
character_set_server = utf8
修改完后Q重启mysql的服务,service mysql restart
使用 mysql> SHOW VARIABLES LIKE 'character%';查看Q发现数据库~码均已Ҏutf8
+--------------------------+---------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:"mysql-5.0.37"share"charsets" |
+--------------------------+---------------------------------+
(2) q有一U修改字W集的方法,是使用mysql的命?br />
mysql> SET character_set_client = utf8 ;
mysql> SET character_set_connection = utf8 ;
mysql> SET character_set_database = utf8 ;
mysql> SET character_set_results = utf8 ;
mysql> SET character_set_server = utf8 ;
mysql> SET collation_connection = utf8 ;
mysql> SET collation_database = utf8 ;
mysql> SET collation_server = utf8 ;
一般就设|了表的默认字符集ؓutf8q且通过UTF-8~码发送查询,你会发现存入数据库的仍然是ؕ码。问题就出在q个connectionq接层上。解x法是在发送查询前执行一下下面这句:
SET NAMES 'utf8';
它相当于下面的三句指令:Java中,反射是一U强大的工具。它使您能够创徏灉|的代码,q些代码可以在运行时装配Q无需在组件之间进行源? 表链接。反允许我们在~写与执 行时Q我们的程序代码能够接入装载到JVM中的cȝ内部信息Q而不是源代码中选定的类协作的代码。这使反成为构建灵zȝ应用的主要工兗但需注意? 是:如果使用不当Q反的成本很高?/font>
Reflection ?Java E序开发语a的特征之一Q它允许q行中的 Java E序对自w进行检查,或者说“自审”Qƈ能直接操作程?的内部属性。Java 的这一能力在实际应用中也许用得不是很多Q但是在其它的程序设计语a中根本就不存在这一Ҏ。例如,Pascal、C 或?C+ + 中就没有办法在程序中获得函数定义相关的信息?/font>
1Q检类Q?/strong>
1.1 reflection的工作机?/strong>
考虑下面q个单的例子Q让我们看看 reflection 是如何工作的?/font>
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}
按如下语句执行:
java DumpMethods java.util.Stack
它的l果输出为:
public java.lang.Object java.util.Stack.push(java.lang.Object)
public synchronized java.lang.Object java.util.Stack.pop()
public synchronized java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized int java.util.Stack.search(java.lang.Object)
q样列Zjava.util.Stack cȝ各方法名以及它们的限制符和返回类型?/font>
q个E序使用 Class.forName 载入指定的类Q然后调?getDeclaredMethods 来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描q某个类中单个方法的一个类?/font>
1.2 Javacd中的主要方?/strong>
对于以下三类lg中的M一cL?-- 构造函数、字D和Ҏ -- java.lang.Class 提供四种独立的反调用,以不同的方式来获得信息。调用都遵@一U标准格式。以下是用于查找构造函数的一l反调用:
Constructor getConstructor(Class[] params) -- 获得使用Ҏ的参数类型的公共构造函敎ͼ
Constructor[] getConstructors() -- 获得cȝ所有公共构造函?/font>
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数cd的构造函?与接入别无?
Constructor[] getDeclaredConstructors() -- 获得cȝ所有构造函?与接入别无?
获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用Q在参数cd数组中用了字段名:
Field getField(String name) -- 获得命名的公共字D?/font>
Field[] getFields() -- 获得cȝ所有公共字D?/font>
Field getDeclaredField(String name) -- 获得cd明的命名的字D?/font>
Field[] getDeclaredFields() -- 获得cd明的所有字D?
用于获得Ҏ信息函数Q?/font>
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方?/font>
Method[] getMethods() -- 获得cȝ所有公共方?/font>
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得cd明的命名的方?/font>
Method[] getDeclaredMethods() -- 获得cd明的所有方?
1.3开始?ReflectionQ?/strong>
用于 reflection 的类Q如 MethodQ可以在 java.lang.relfect 包中扑ֈ。用这些类的时候必要遵@三个步骤Q第一步是获得你想操作的类?java.lang.Class 对象。在q行中的 Java E序中,?java.lang.Class cL描述cd接口{?/font>
下面是获得一?Class 对象的方法之一Q?/font>
Class c = Class.forName("java.lang.String");
q条语句得到一?String cȝcd象。还有另一U方法,如下面的语句Q?/font>
Class c = int.class;
或?/font>
Class c = Integer.TYPE;
它们可获得基本类型的cM息。其中后一U方法中讉K的是基本cd的封装类 (?Integer) 中预先定义好?TYPE 字段?/font>
W二步是调用诸如 getDeclaredMethods 的方法,以取得该cM定义的所有方法的列表?/font>
一旦取得这个信息,可以进行第三步了——?reflection API 来操作这些信息,如下面这D代码:
Class c = Class.forName("java.lang.String");
Method m[] = c.getDeclaredMethods();
System.out.println(m[0].toString());
它将以文本方式打印出 String 中定义的W一个方法的原型?/font>
在下面的例子中,q三个步骤将Z?reflection 处理Ҏ应用E序提供例证?/font>
模拟 instanceof 操作W?/font>
得到cM息之后,通常下一个步骤就是解军_?Class 对象的一些基本的问题。例如,Class.isInstance Ҏ可以用于模拟 instanceof 操作W:
class A {
}
public class instance1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("A");
boolean b1 = cls.isInstance(new Integer(37));
System.out.println(b1);
boolean b2 = cls.isInstance(new A());
System.out.println(b2);
} catch (Throwable e) {
System.err.println(e);
}
}
}
在这个例子中创徏了一?A cȝ Class 对象Q然后检查一些对象是否是 A 的实例。Integer(37) 不是Q但 new A() 是?/font>
1.4 扑ևcȝҎ 扑և一个类中定义了些什么方法,q是一个非常有价g非常基础?reflection 用法。下面的代码实Cq一用法Q?/font> import java.lang.reflect.*; public class method1 { public static void main(String args[]) { q?
个程序首先取?method1 cȝ描述Q然后调?getDeclaredMethods 来获取一pd?Method
对象Q它们分别描qC定义在类中的每一个方法,包括 public Ҏ、protected Ҏ、package Ҏ?private
Ҏ{。如果你在程序中使用 getMethods 来代?getDeclaredMethodsQ你q能获得l承来的各个Ҏ的信息?/font> 取得?Method 对象列表之后Q要昄q些Ҏ的参数类型、异常类型和q回值类型等׃难了。这些类型是基本cdq是cȝ型,都可以由描述cȝ对象按顺序给出?/font> 输出的结果如下: name = f1 decl class = class method1 param #0 class java.lang.Object param #1 int exc #0 class java.lang.NullPointerException return type = int ----- name = main decl class = class method1 param #0 class [Ljava.lang.String; return type = void ----- 获取cL造器的用法与上述获取Ҏ的用法类|如: import java.lang.reflect.*; public class constructor1 { protected constructor1(int i, double d) { public static void main(String args[]) { q个例子中没能获得返回类型的相关信息Q那是因为构造器没有q回cd?/font> q个E序q行的结果是Q?/font> name = constructor1 decl class = class constructor1 ----- name = constructor1 decl class = class constructor1 param #0 int param #1 double ----- 1.6获取cȝ字段(? 扑և一个类中定义了哪些数据字段也是可能的,下面的代码就在干q个事情Q?/font> ?Q?br />
import java.lang.reflect.*; public class field1 { public static void main(String args[]) { q?
个例子和前面那个例子非常怼。例中用了一个新东西 ModifierQ它也是一?reflection
c,用来描述字段成员的修饰语Q如“private int”。这些修饰语自n由整数描qͼ而且使用 Modifier.toString
来返回以“官方”序排列的字W串描述 (?#8220;static”?#8220;final”之前)。这个程序的输出是: name = d decl class = class field1 type = double modifiers = private ----- name = i decl class = class field1 type = int modifiers = public static final ----- name = s decl class = class field1 type = class java.lang.String modifiers = ----- ?: import java.lang.reflect.*; 输出: Height:325 和获取方法的情况一下,获取字段的时候也可以只取得在当前cMx了的字段信息 (getDeclaredFields)Q或者也可以取得父类中定义的字段 (getFields) ?/font> 文本到这里,所丄例子无一例外都与如何获取cȝ信息有关。我们也可以?reflection 来做一些其它的事情Q比如执行一个指定了名称的方法。下面的CZ演示了这一操作Q?/font> ?: import java.lang.reflect.*; 假如一个程序在执行的某处的时候才知道需要执行某个方法,q个Ҏ的名U是在程序的q行q程中指定的 (例如QJavaBean 开发环境中׃做这L?Q那么上面的E序演示了如何做到?/font> ?
例中QgetMethod 用于查找一个具有两个整型参C名ؓ add 的方法。找到该Ҏq创Z相应?Method
对象之后Q在正确的对象实例中执行它。执行该Ҏ的时候,需要提供一个参数列表,q在上例中是分别包装了整?37 ?47 的两?Integer
对象。执行方法的q回的同h一?Integer 对象Q它装了返回?84?/font> ?Q?/p>
import java.lang.reflect.Method;
private int f1(Object p, int x) throws NullPointerException {
if (p == null)
throw new NullPointerException();
return x;
}
try {
Class cls = Class.forName("method1");
Method methlist[] = cls.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
Method m = methlist[i];
System.out.println("name = " + m.getName());
System.out.println("decl class = " + m.getDeclaringClass());
Class pvec[] = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("return type = " + m.getReturnType());
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
1.5 获取构造器信息
public constructor1() {
}
}
try {
Class cls = Class.forName("constructor1");
Constructor ctorlist[] = cls.getDeclaredConstructors();
for (int i = 0; i < ctorlist.length; i++) {
Constructor ct = ctorlist[i];
System.out.println("name = " + ct.getName());
System.out.println("decl class = " + ct.getDeclaringClass());
Class pvec[] = ct.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = ct.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
private double d;
public static final int i = 37;
String s = "testing";
try {
Class cls = Class.forName("field1");
Field fieldlist[] = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name = " + fld.getName());
System.out.println("decl class = " + fld.getDeclaringClass());
System.out.println("type = " + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers = " + Modifier.toString(mod));
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
import java.awt.*;
class SampleGet {
public static void main(String[] args) {
Rectangle r = new Rectangle(100, 325);
printHeight(r);
}
static void printHeight(Rectangle r) {
Field heightField;
Integer heightValue;
Class c = r.getClass();
try {
heightField = c.getField("height");//取得heightq个变量
heightValue = (Integer) heightField.get(r);//取得heightq个变量的?br />
System.out.println("Height: " + heightValue.toString());
} catch (NoSuchFieldException e) {
System.out.println(e);
} catch (SecurityException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
}
}
}
1.7 ҎҎ的名U来执行Ҏ
public class method2 {
public int add(int a, int b) {
return a + b;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = meth.invoke(methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println(retval.intvalue());
} catch (Throwable e) {
System.err.println(e);
}
}
}
//Base.java 抽象基类
//Son1.java 基类扩展1
//Son2.java 基类扩展2
//Util.java
//Base.java 抽象基类只是一个定?br />
abstract class Base {
}
//Son1.java 是已l实现的Base
class Son1 extends Base {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void son1Method(String s) {
System.out.println(s);
}
}
// Son2.java 是已l实现的Base
class Son2 extends Base {
private int id;
private double salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
// Util.java 演示了如何根据指定的cdQ类字段名和所对应的数据,得到一个类的实?br />
public class Util {
// 此方法的最大好处是没有cdSon1,Son2 可以通过参数来指定,E序里面Ҏ不用出现
public static Base utilDo(String beanName,
String methodName, String paraValue) {
Base base = null;
try {
Class cls = Class.forName(beanName);//生成c?br />
base = (Base) cls.newInstance();//生成cȝ对象
Class[] paraTypes = new Class[] { String.class};
Method method = cls.getMethod(methodName, paraTypes);// fieldSetter为方法的名称;paraTypesҎ的参数数l?要用cȝ形式
String[] paraValues = new String[] { paraValue };
method.invoke(base, paraValues);//执行Ҏ
} catch (Throwable e) {
System.err.println(e);
}
return base;
}
public static void main(String[] args) {
Son1 son1 = (Son1) Util.utilDo("test.Reflection.Son1",
"setName", "I am son1");// 表示cȝ字符串一定要是类?#8220;全类?#8221;,q里?/font>test.Reflection.Son1
System.out.println("son1.getName() :" + son1.getName());
}
}
输出Qson1.getName() :I am son1
1.8 创徏新的对象 对于构造器Q则不能像执行方法那栯行,因ؓ执行一个构造器意味着创徏了一个新的对?(准确的说Q创Z个对象的q程包括分配内存和构造对?。所以,与上例最怼的例子如下: import java.lang.reflect.*; public class constructor2 { public constructor2(int a, int b) { public static void main(String args[]) { Ҏ指定的参数类型找到相应的构造函数ƈ执行它,以创Z个新的对象实例。用这U方法可以在E序q行时动态地创徏对象Q而不是在~译的时候创建对象,q一炚w常有价倹{?/font> 1.9 改变字段(?的?/font> reflection 的还有一个用处就是改变对象数据字D늚倹{reflection 可以从正在运行的E序中根据名U找到对象的字段q改变它Q下面的例子可以说明q一点: import java.lang.reflect.*; public class field2 { public static void main(String args[]) { q个例子中,字段 d 的D变ؓ?12.34?/font> 1.10 使用数组 本文介绍?reflection 的最后一U用法是创徏的操作数l。数l在 Java 语言中是一U特D的cȝ型,一个数l的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的: import java.lang.reflect.*; public class array1 { 例中创徏?10 个单位长度的 String 数组QؓW?5 个位|的字符串赋了|最后将q个字符串从数组中取得ƈ打印了出来?/font> 下面q段代码提供了一个更复杂的例子: import java.lang.reflect.*; public class array2 { 注意创徏数组时的cd是动态的Q在~译时ƈ不知道其cd?/font>
public constructor2() {
}
System.out.println("a = " + a + " b = " + b);
}
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct = cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
} catch (Throwable e) {
System.err.println(e);
}
}
}
public double d;
try {
Class cls = Class.forName("field2");
Field fld = cls.getField("d");
field2 f2obj = new field2();
System.out.println("d = " + f2obj.d);
fld.setDouble(f2obj, 12.34);
System.out.println("d = " + f2obj.d);
} catch (Throwable e) {
System.err.println(e);
}
}
}
public static void main(String args[]) {
try {
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test");
String s = (String) Array.get(arr, 5);
System.out.println(s);
} catch (Throwable e) {
System.err.println(e);
}
}
}
public static void main(String args[]) {
int dims[] = new int[]{5, 10, 15};
Object arr = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls = arrobj.getClass().getComponentType();
System.out.println(cls);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][]) arr;
System.out.println(arrcast[3][5][10]);
}
}
?
中创Z一?5 x 10 x 15 的整型数l,qؓ处于 [3][5][10] 的元素赋了gؓ
37。注意,多维数组实际上就是数l的数组Q例如,W一?Array.get 之后Qarrobj 是一?10 x 15
的数l。进而取得其中的一个元素,即长度ؓ 15 的数l,q?Array.setInt 为它的第 10 个元素赋倹{?/font>