构建器&反射&JDBC

构建者模式(多可选参数)&静态工厂&单例设计模式

一个营养产品类,该类含有两个必选参数和许多可选参数,代表了该营养产品的营养成分

package xiaobai;

public class NutritionFacts{
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder{// Builder内部类,用来创建返回对象
        // Required parameters,必选参数
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values,可选参数
        private int calories = 0;
        private int fat = 0;
        private int carbohydrate = 0;
        private int sodium = 0;

        public Builder(int servingSize,int servings){
            this.servingSize = servingSize;
            this.servings = servings;
        }// 每个设置参数的方法返回this,构建器

        public Builder calories(int val){
            calories = val;
            return this;
        }
        public Builder fat(int val){
            fat = val;
            return this;
        }
        public Builder carbohydrate(int val){
            carbohydrate = val;
            return this;
        }
        public Builder sodium(int val){
            sodium = val;
            return this;
        }

        public NutritionFacts build(){// 返回类的对象
            return new NutritionFacts(this);
        }

    }// 内部类结束

    private NutritionFacts(Builder builder){// 单例设计模式-构造器私有化,静态工厂返回对象
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium; 
        carbohydrate = builder.carbohydrate;
    }
}

创建对象时的代码:

package xiaobai;

import xiaobai.NutritionFacts;

public class Test {
    public static void main(String[] args) {
        NutritionFacts cocaCola = new NutritionFacts.Builder(240,8)
                .carbohydrate(100).sodium(35).carbohydrate(27).build();
    }
}

使用构建者模式在遇到有多个可选参数的类时,可以极大的简化代码,同时可以在创建对象时使代码更加的清晰易懂。而单例设计模式私有化构造器,可以保证在一定情况下在所有的区域内只能存在一个该类的对象,本例中的对象不是唯一的。


数组和List的相互转换

  • 一维数组与一维集合的转换
// 一维数组 转 一维集合
String[] strArr1 = {"one","two","three","four"};
List<String> list = Arrays.asList(strArr);
// 一维集合 转 一维数组
String[] strArr2 = list.toArray(new String[]{});
  • 二维数组与二维集合的转换
// 二维数组 转 二维集合
String[][] strArr2 = {
    {"one","two","three","four"},
    {"one","two","three","four"},
    {"one","two","three","four"}
};
// 对象创建使用多态,但泛型必须一致,左右都为List<String>
List<List<String>> list = new ArrayList<List<String>>();
for(int i=0;i<strArr2.length;i++){
    list.add(array2List(strArr2[i]));// 调用下面的方法
}
// 完成一维数组转一维集合的功能
public static List<String> array2List(String[] strArr){
    List<String> list = Arrays.asList(strArr);
    return list;
}

泛型

给一个类或方法一个动态的参数类型,这样可以加强我们代码的复用性,一个类可以应用在所有类的情况,同时在使用时不会产生由于类型不明导致的编译错误。

// 泛型类
public class GenericClass<E> {
    private E e;
    public E getE(){
        return e;
    }
    public void setE(E e){
        this.e = e;
    }
    public static void main(String[] args) {
        GenericClass<String> gc = new GenericClass<String>();
        gc.setE("abc");
        System.out.println(gc.getE());
    }
}


// 泛型方法:修饰符和方法的返回值类型之间加泛型
public class GenericClass{
public <E> void swap(E e1,E e2){
    System.out.println(e1 + ":" + e2);
    E temp = e1;
    e1 = e2;
    e2 = temp;
    System.out.println(e1 + ":" + e2);
}
public static void main(String[] args) {
    GenericClass gc = new GenericClass();
    gc.swap("one", "two");
    gc.swap(1, 2);
}
}

枚举

一个类中只有固定的几个该类的对象,如一个季节类中只有春、夏、秋、冬四个对象。此时就可以用枚举代替类,使代码简单清晰。如果不使用枚举,就需要使用单例模式,私有化构造器,然后将本类的对象作为本类的静态属性。

// 交通信号灯类,只有红、绿、黄三个对象,就可以写为一个枚举。如果正常创建类
public enum LightEnum{
// 提供固定的几个本类对象作为该类的静态属性
    public static final LightEnum RED = new LightEnum();
    public static final LightEnum GREEN = new LightEnum();
    public static final LightEnum YELLOW = new LightEnum();

    private LightEnum(){// 私有化构造器
        super();
    }
}

写为一个枚举如下:

public enum LightEnum {
    RED,GREEN,YELLOW;// 三个本类的对象
}

// 测试类
public class TestEnum {
    public static void main(String[] args) {
        LightEnum le1 = LightEnum.RED;
        LightEnum le2 = LightEnum.GREEN;
        LightEnum le3 = LightEnum.YELLOW;
        System.out.println(le1);

        LightEnum[] leArr = LightEnum.values();// 返回枚举的所有对象
        System.out.println(Arrays.toString(leArr));
    }
}

反射

在Java中,万物皆对象。那么我们将所有的类视为一个特殊的类的对象,每新建一个类就是给这个特殊类新建了一个对象。或我们起一个别名叫初代,而我们通常使用的类全部都是初代的对象,这个初代在Java官方给出的就是类Class。像String,Math,Object等都是初代的一个对象。而通过初代的方法来反向获取一个类和这个类中的属性、方法的过程就叫做反射。

  • 获取Class对象的方法
// 1、包名.类名  数据库驱动加载  框架中(从xml配置文件中根据类名称获取类对象,执行类的方法)
Class c1 = Class.forName("cn.ucai.day26.Person");
// 2、多用于传参
Class c2 = Person.class;
// 3、通过类的对象的方法返回一个Class对象
Person p = new Person();
Class c3 = p.getClass();
  • 通过反射获取类的所有方法 并可以执行方法
private static void showMethods(Class c) throws Exception{
    // 获得所有的方法(修饰符、返回值类型、方法名、参数、抛出的异常)
    Method[] methodArr = c.getDeclaredMethods();
    for(Method method : methodArr){
            System.out.print(Modifier.toString(method.getModifiers())+" ");
            System.out.print(method.getReturnType().getSimpleName()+" ");// 返回值类型
            System.out.print(method.getName()+" ");
            Class[] paArr = method.getParameterTypes();// 得到方法的参数类型
            System.out.print(Arrays.toString(paArr)+" ");
            Class[] excArr = method.getExceptionTypes();
            System.out.println(Arrays.toString(excArr));
        }
        // 获得指定的方法  如何执行指定的方法
        Method method = c.getDeclaredMethod("setName",new Class[]{String.class});
        Person p = (Person) c.newInstance();// 调用Person的无参构造,创建Person对象
        //method.setAccessible(true);使方法可见,打破了封装性
        // 执行这个方法
        method.invoke(p,"张三");// p.setName("张三");

        Method methodGetName = c.getDeclaredMethod("getName");
        String s = (String) methodGetName.invoke(p);// String s = p.getName();
        System.out.println(s);// 张三
    }
  • 通过反射获取类的所有字段 并可以给字段赋值
private static void showFields(Class c) throws Exception{
    Field[] fieldArr = c.getDeclaredFields();
    for(Field field : fieldArr){
        System.out.print(Modifier.toString(field.getModifiers())+" ");
        // java.lang.String ==> String
        System.out.print(field.getType().getSimpleName()+" ");
        System.out.println(field.getName());
    }
    // 获得指定的属性 
    Field field = c.getDeclaredField("name");
    Person p = (Person) c.newInstance();// Person p = new Person();
    field.setAccessible(true);
    field.set(p, "张三");// p.setName("张三");
    System.out.println(p);
}
  • 通过反射获取类的所有构造方法 并执行构造方法创建对象
private static void showConstructors(Class c) throws Exception{
    // 取得所有的构造方法
    Constructor[] conArr = c.getDeclaredConstructors();
    for(Constructor con:conArr){
        // 取得构造方法的修饰符
        int modi = con.getModifiers();
        String strModi =Modifier.toString(modi);// 对应数字转为了public 、private 等
        System.out.print(strModi+" ");
        System.out.print(con.getName()+" ");
        // 得到参数的类型
        Class[] claArr = con.getParameterTypes();// String.class int.class Class对象
        System.out.print(Arrays.toString(claArr)+" ");
        // 得到异常的类型
        Class[] excArr = con.getExceptionTypes();// Exception.class NullPointerException.class
        System.out.println(Arrays.toString(excArr));
    }
    // 根据Class对象获得指定某个类的指定参数的构造方法并执行去创建对象
    Constructor cons = 
            c.getDeclaredConstructor(new Class[]{String.class,int.class});
    cons.setAccessible(true);// 破坏类的封装性
    Object o = cons.newInstance("张三",20);// new Person("张三",20);
    System.out.println(o.toString());
}
  • 假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个 程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个 程序员所写的类的时候,来完成自身代码的编译。例如Tomcat中的代码就是采用了反射机制,我们在配置文件时采用了一下方式:
  <servlet>
    <servlet-name>Hello</servlet-name>
    <servlet-class>cn.ucai.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
// HelloServlet类中doGet方法被调用
在Tomcat的代码中:
Class c = Class.forName("cn.ucai.servlet.HelloServlet");
HttpServlet hs = c.newInstance();
hs.doGet();

MySQL数据库

cmd窗口对于数据库的几个简单操作指令:
show databases;–查看全部数据库
use 数据库名;–使用某指定数据库
select * from 表名;–查看某数据表中的全部数据

下面是我目前使用的MySql数据库的下载连接:
mysql-5.5.48
下面是安装教程:
mysql安装教程
mysql数据库实现了很强大的数据库功能,但是操作只能在cmd窗口用命令行操作,有时非常不易操作,下面是一个mysql界面化的软件下载,下载完成后直接快速安装就可以:
Navicat_Premium_11.0.10
最后是一个Navicat_Premium的破解工具:
PatchNavicat


JDBC(Java Database Connection)

  • 什么是JDBC:JDBC是我们代码与数据库相关联使用的语言

  • 使用代码完成数据的访问与操作
    1.加载驱动
    2.连接数据库
    3.得到操作数据库的类
    4.使用该类操作数据库
    5.得到查询结果集
    6.遍历结果集
    7.断开连接

  • 在Eclipse相应工程src文件夹下创建一个配置文件jdbc.properties

jdbcDriver=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:/localhost:3306/xiaobai?user=root&password=root
// xiaobai是要访问的数据库名,user、password是数据库的登录用户名和密码
  • 获得配置文件中的值
public class PropertiesUtil {
    /**
     * 通过指定的key,取得properties文件中指定的value值
     * @param key
     * @param proName 要访问的文件名
     * @return
     */
    public static String getValue(String key, String proName){
        String value = null;
        Properties p = new Properties();
        String path = PropertiesUtil.class.getResource("/").getPath();
        try {
            // 指定p所表示的properties
            p.load(new FileInputStream(new File(path,proName)));
            value = p.getProperty(key);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return value;
    }
}
  • 创建一个工具类
/**
 * 数据库操作的工具类:
 * 1、完成数据库的连接
 * 2、完成数据库的关闭
 */
public class DBUtils {
    /**
     * 完成数据库的连接
     * @return 数据库连接Connection对象
     */
    public static Connection getConnection(){
        Connection conn = null;
        try {
            Class.forName(PropertiesUtil.getValue("jdbcDriver", "jdbc.properties"));
            conn = DriverManager
                    .getConnection(PropertiesUtil.getValue("jdbcUrl", "jdbc.properties"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭全部内容
     * @param conn
     * @param st
     * @param rs
     */
    public static void closeAll(Connection conn,Statement st,ResultSet rs){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 访问数据库
public static List<Student> getAll() {
        List<Student> list = new ArrayList<Student>();
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            // 获取连接
            conn = DBUtils.getConnection();
            // 得到操作数据库的类的对象
            st = conn.createStatement();
            // 通过executeQuery,执行查询的sql语句,数据库中要存在该表
            rs = st.executeQuery("select * from t_student");
            // 遍历结果集
            // rs.next();// 相当于Iterator中的hasNext()和next()
            while (rs.next()) {
                // 根据字段,取数据
                int id = rs.getInt("sid");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                // 实体类,对应t_student数据表中的各列,一个对象代表数据库中一行数据
                Student student = new Student(id, name, age);
                list.add(student);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
        // 关闭内容
            DBUtils.closeAll(conn, st, rs);
        }
        return list;
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值