在Java的20周年的记念日的日子里,让咱们来从新温习下Java里面的高级知识,Java确定但愿你们了解她,要否则你跟她每天相濡以沫了这么长时间,让她知道你居然不了解她,不在意她,那么她该有多伤心呢,因此咱们不该该作一个负心汉,更不该该作一个忘恩负义的人,她教会了你生存的技能,因此咱们也应该将她发扬光大!
Java的核心技能有以下几项:
(1)JVM的调优
(2)类加载器
(3)反射
(4)动态编译
(5)动态代理
(6)注解
(7)多线程
(8)IO,NIO,Socket,Channel等网络编程
除了JAVA的基础,面向对象的思想外,这些既是java里面核心技术,也是面试时候,面试官常常爱问的几个知识,了解,熟悉和掌握他们的重要性不言而喻,今天就先来谈谈反射。
反射给java提供了,运行时获取一个类实例的可能,这一点很是灵活,你仅仅传一个类的全包名路径,就能经过反射,来获取对应的类实例,咱们通常会用Class类,来调用这个被反射的Objcet类下的,构造方法,属性,或方法等,反射在一些开源框架里用的很是之多,Spring,Struts,Hibnerate,MyBatics都有它的影子,反射虽然很灵活,可以使得写的代码,变的大幅精简,因此在用的时候,必定要注意具体的应用场景,反射的优缺点以下:
优势:
(1)可以运行时动态获取类的实例,大大提升系统的灵活性和扩展性。
(2)与Java动态编译相结合,能够实现无比强大的功能
缺点:
(1)使用反射的性能较低
(2)使用反射相对来讲不安全
(3)破坏了类的封装性,能够经过反射获取这个类的私有方法和属性
任何事物,都有两面性,反射的优势,也同是就是它的缺点,因此,没有好与坏,只有最合适的场景,一阴一阳,才是天道平衡的条件。
下面来看个,使用java反射,来自动封装数据库对应的表的例子,初学java的人都会给每一个实体类创建一个Dao对象,来专门操做这个对象对应的表,这样作没错,很好,是分层,分工明确的一个表现,可是若是有几十个实体类,那么这种重复增删改查的工做,就会大大增长,散仙初入门的时候也有如此的感觉,虽然咱们能够经过,抽象类和接口,使用适配器的设计模式来简化重复的代码,可是不可避免的就是类的臃肿了,下面看看如何使用反射来搞定这么多实体类的重复的增删改查的代码:
使用前提:
(1)每个实体类都会对应一个数据库表
(2)每一个表的列,与对应的实体类的属性名是同样的
(3)实体类要提供基本的get或set方法

实体类以下: java
Java代码 mysql
- package com.qin.model;
- public class Dog {
-
- private int id;
- private String name;
- private String type;
- private String color;
- private int weight;
- 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 String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- public int getWeight() {
- return weight;
- }
- public void setWeight(int weight) {
- this.weight = weight;
- }
- public Dog() {
- // TODO Auto-generated constructor stub
- }
- public Dog(int id, String name, String type, String color, int weight) {
- super();
- this.id = id;
- this.name = name;
- this.type = type;
- this.color = color;
- this.weight = weight;
- }
- @Override
- public String toString() {
- return "Dog [id=" + id + ", name=" + name + ", type=" + type + ", color="
- + color + ", weight=" + weight + "]";
- }
-
-
-
-
- }
Java代码 面试
- package com.qin.model;
-
- public class Person {
-
- private int id;
- private String name;
- private int age;
- private String address;
- 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 int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getAddress() {
- return address;
- }
- public void setAddress(String address) {
- this.address = address;
- }
-
- public Person() {
- // TODO Auto-generated constructor stub
- }
- public Person(int id, String name, int age, String address) {
- super();
- this.id = id;
- this.name = name;
- this.age = age;
- this.address = address;
- }
- @Override
- public String toString() {
- return "Person [id=" + id + ", name=" + name + ", age=" + age
- + ", address=" + address + "]";
- }
-
-
-
- }
Java代码 sql
- package com.qin.db;
-
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- /**
- * 数据库链接的
- * 测试类
- * @author qindongliang
- *
- *
- * **/
- public class ConnectionFactory {
-
- public static Connection getCon()throws Exception{
- Class.forName("com.mysql.jdbc.Driver");
- //加上字符串编码指定,防止乱码
- Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/rate?characterEncoding=utf8", "root", "qin");
- return connection;
- }
-
-
- public static void main(String[] args) throws Exception {
-
- Class.forName("com.mysql.jdbc.Driver");
- Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/rate", "root", "qin");
- System.out.println(connection);
- connection.close();
-
-
- }
-
- }
Java代码 数据库
- package com.qin.commons;
-
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.util.ArrayList;
- import java.util.List;
-
- import com.qin.db.ConnectionFactory;
- import com.qin.model.Dog;
- import com.qin.model.Person;
- /***
- * 反射自动查询和封装的类
- *@author qindongliang
- *
- * */
- public class CommonSupport {
-
-
- /**
- * @param obj须要保存的对象
- * @param string 保存对象的sql语句
- * */
- public static String createSqlByObject(Object obj){
-
- StringBuffer sb=new StringBuffer("insert into ");
-
- //获得对象的类
- Class c=obj.getClass();
- //获得对象中的全部方法
- Method[] ms=c.getMethods();
-
- //获得对象中全部的属性,虽然在这个里面就能获取全部的字段名,但不建议这么用,破坏类的封装性
- Field[] fs=c.getDeclaredFields();
- //获得对象类的名字
- String cname=c.getName();
- System.out.println("类名字: "+cname);
- //表名字
- String tableName=cname.split("\\.")[cname.split("\\.").length-1];
- System.out.println("表名字: "+tableName);
- //追加表名和(左边的符号
- sb.append(tableName).append(" (");
- //存放列名的集合
- List<String> columns=new ArrayList<String>();
- //存放值的集合
- List values=new ArrayList();
- //遍历方法
- for(Method m:ms){
- String methodName=m.getName();//获取每个方法名
- //只获得具备get方法的属性,getClass除外
- if(methodName.startsWith("get")&&!methodName.startsWith("getClass")){
- //System.out.println("属性名:"+methodName);
- String fieldName = methodName.substring(3, methodName.length());
- // System.out.println("字段名:"+fieldName);
- columns.add(fieldName);//将列名添加到列名的集合里
- try{
- Object value=m.invoke(obj, null);
- //System.out.println("执行方法返回的值:"+value);
- if(value instanceof String){
- // System.out.println("字符串类型字段值:"+value);
- values.add("'"+value+"'");//加上两个单引号,表明是字符串类型的
- }else{
- // System.out.println("数值类型字段值:"+value);
- values.add(value);//数值类型的则直接添加
- }
-
- }catch(Exception e){
- e.printStackTrace();
- }
-
- }
-
- }
-
-
- for(int i=0;i<columns.size();i++){
- String column=columns.get(i);
- Object value=values.get(i);
- System.out.println("列名:"+column+" 值: "+value);
- }
-
- //拼接列名
- for(int i=0;i<columns.size();i++){
- if(i==columns.size()-1){
- sb.append(columns.get(i)).append(" ) ");
- }else{
- sb.append(columns.get(i)).append(" , ");
- }
- }
- System.out.println(" 拼接列名后的sql:"+sb.toString());
- sb.append(" values ( ");
- //拼接值
- for(int i=0;i<values.size();i++){
- if(i==values.size()-1){
- sb.append(values.get(i)).append(" ) ");
- }else{
- sb.append(values.get(i)).append(" , ");
- }
- }
-
- System.out.println(" 拼接值后的sql:"+sb.toString());
-
- //返回组装的sql语句
- return sb.toString();
- }
-
- /**
- * 将对象保存在数据库中
- * @param obj 保存的对象
- * **/
- public static void addOne(Object obj){
- try {
- Connection con=ConnectionFactory.getCon();
- String sql=createSqlByObject(obj);
- PreparedStatement ps=con.prepareStatement(sql);
- int result=ps.executeUpdate();
- if(result==1){
- System.out.println("保存成功!");
- }else{
- System.out.println("保存失败!");
- }
- ps.close();
- con.close();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
- /**
- * 根据类名字和一个查询条件
- * 自动封装一个Bean对象
- * @param columnName 列名
- * @param value 列值
- * @return {@link Object}
- *
- * */
- public static Object getOneObject(String className,String columnName,String value){
-
- String tableName=className.split("\\.")[className.split("\\.").length-1];
- System.out.println("表名字: "+tableName);
-
- //根据类名来建立对象
- Class c=null;
- try{
- c=Class.forName(className);//反射生成一个类实例
- }catch(Exception e){
- e.printStackTrace();
- }
- //拼接sql语句
- StringBuffer sb=new StringBuffer();
- sb.append("select * from ")
- .append(tableName)
- .append(" where ")
- .append(columnName).append(" = ").append("'").append(value).append("'");
-
- String querySql=sb.toString();
- System.out.println("查询的sql语句为:"+querySql);
-
- Object obj=null;
- try{
- Connection con=ConnectionFactory.getCon();//获得一个数据库链接
- PreparedStatement ps=con.prepareStatement(querySql);//预编译语句
- ResultSet rs=ps.executeQuery();//执行查询
- //获得对象的全部的方法
- Method ms[]=c.getMethods();
-
- if(rs.next()){
- //生成一个实例
- obj=c.newInstance();
-
- for(Method m:ms){
- String mName=m.getName();
- if(mName.startsWith("set")){
- //根据方法名字自动提取表中对应的列名
- String cname = mName.substring(3, mName.length());
- //打印set的方法名
- // System.out.println(cname);
- //获得方法的参数类型
- Class[] params=m.getParameterTypes();
- // for(Class cp : params){
- // System.out.println(cp.toString());
- // }
- //若是参数是String类型,则从结果集中,按照列名取到的值,进行set
- //从params[0]的第一个值,能获得该数的参数类型
- if(params[0]==String.class){//
- m.invoke(obj, rs.getString(cname));
- //若是判断出来是int形,则使用int
- }else if(params[0]==int.class){
- m.invoke(obj, rs.getInt(cname));
- }
- }
- }
-
-
-
- }else{
- System.out.println("请注意:"+columnName+"="+value+"的条件,没有查询到数据!!");
- }
- rs.close();
- ps.close();
- con.close();
- }catch(Exception e){
- e.printStackTrace();
- }
-
-
-
- return obj;
- }
-
- public static void main(String[] args) throws Exception{
- //====================添加======================
- Dog d=new Dog(21, "小不点", "藏獒", "灰色", 25);
- Person p=new Person(6, "大象hadoop", 10, "家住Apache基金组织");
- //createSqlByObject(d);
- //addOne(d);给dog表添加一条数据
- //addOne(p);//给person表添加一条数据
-
- //=======================查询=======================
- //强制转换为原始类
- // Dog d1=(Dog)getOneObject("com.qin.model.Dog", "id", "1");
- // System.out.println(d1);
-
- Person d1=(Person)getOneObject("com.qin.model.Person", "id", "1");
- //Person d1=(Person)getOneObject("com.qin.model.Person", "name", "王婷");
- System.out.println(d1);
-
- }
-
- }
代码量是很是的少的,并且具备通用型,若是再有10个这个实体类,咱们代码根本不用任何改动,只须要传入不一样的实体类名字便可,固然这一点和Hibernate的自动化ORM很是接近了,在Hibnerate里,能够自动经过表生成类,也能够经过类生成数据库的表,原理其实就是利用了反射的特性,帮咱们作了大量的重复工做,固然Hibnerate提供了更多的特性,也这只是一个简单的例子,具体的应用场景中,咱们也须要因地制宜,不然,则为拔苗助长! 编程