20145107 《Java程序设计》第九周学习总结

20145107 《Java程序设计》第九周学习总结

教材学习内容总结

在本周,我们进行了书中第十六,十七,十八章的学习。本周的学习目标是:
了解JDBC架构
掌握JDBC架构
掌握反射与ClassLoader
了解自定义泛型和自定义枚举
会使用标准注解

第十六章:

JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则使用JDBC接口进行操作,本章讲的就是JDBC的一些基础操作。JDBC标准主要分为两个部分:JDBC应用程序开发者接口以及JDBC驱动程序开发者接口。如果你的应用程序需要联机数据库,就是调用JDBC应用开发接口。如果将来要换为Oracle数据库,只要置换Oracle驱动程序。
而厂商在操作JDBC时,可以按照操作方式将驱动程序分为四种类型:

  • 1.JDBC-ODBC Bridge Driver:
    这是由微软公司主导的数据库连接标准,基本上,,JDBC是按照ODBC的参考制定而来,所以,ODBC在微软的操作系统上最为成熟,在office Access中的数据库就是使用ODBC。虽然ODBC与JDBC有很多的相同通用之处,但两者并非是一一对应的,所以部分调用无法直接转换因此存在一些功能的限制。
  • 2.Native API Driver:
    Native API Driver会以原生的方式条用数据库提供的原生链接库,JDBC的方法调用都会转换为原生链接库中相关的数据库调用。
  • 3.JDBC NET-Driver
    这个类型的JDBC驱动程序会将JDBC方法调用转换为特定的网络协议调用,目的是远程与数据库特定的中介服务器或组件进行协议操作。
  • 4.Native Protocol Driver
    这种类型的驱动程序的主要作用是将JDBC转化为特定的网络协议,所以此程序也可以使用原生的Java技术来实现,所以,这种类型的驱动程序可以跨平台,在效能上也有很好的表现。

第十七章:

反射:
  • 1.class与class文档:
    在Java的程序中,只有真正需要某个类时才会加载对应的.class文档,而不是在程序启动时就加在所有的类。所以大多数的用户只会使用应用程序的部分资源,在需要某些功能的时候才会加载对应的资源,这样可以使程序的运行变得更有效率。
    java.lang.Class的实例的代表了Java应用程序运行时加载的.class文档,类,接口编译后哦都会生成相应的.class文档。我们可以使用Object中的getchar()方法,或者是通过class常量取得每个对象对应的class对象。在取得对应的对象后,就可以操作class对象的公开方法取的类的信息就像下面的程序:
package Reflection;

        import static java.lang.System.out;

public class ClassInfo {
    public static void main(String[] args) {
        Class clz = String.class;
        out.println("类别名称:" + clz.getName());
        out.println("是否为接口:" + clz.isInterface());
        out.println("是否为基本类型:" + clz.isPrimitive());
        out.println("是否为数组对象:" + clz.isArray());
        out.println("父类名称:" + clz.getSuperclass().getName());
    }
}

程序运行的程序截图如下:

some类定义了static的区块系统默认首次加载都会执行静态区块,通过在文本模式显示下可以了解如何生成加载.class文件。就像下面的程序:

package Reflection;
public class some {
    static {
        System.out.println("载入 Some.class 档案");
    }
}

package Reflection;

        import static java.lang.System.out;

public class SomeDemo {
    public static void main(String[] args) {
        some s;
        out.println("宣告 Some 参考名称");
        s = new some();
        out.println("生成 Some 实例");
    }
}

程序生成图如下所示:

  • 2.使用Class.forName:
    在某些应用中,无法实现知道开发人员使用那个类,我们可以使用Class.forName()方法实现加载动态类,可以使用字符串指定名称活的累的相关信息:

package Reflection;



        import static java.lang.System.out;

public class InfoAbout {
    public static void main(String[] args) {
        try {
            Class clz = Class.forName(args[0]);
            out.println("类的名称:" + clz.getName());
            out.println("是否为接口:" + clz.isInterface());
            out.println("是否为基本类型:" + clz.isPrimitive());
            out.println("是否为数组:" + clz.isArray());
            out.println("父类:" + clz.getSuperclass().getName());
        } catch (ArrayIndexOutOfBoundsException e) {
            out.println("没有指定名称");
        } catch (ClassNotFoundException e) {
            out.println("找不到指定类别 " + args[0]);
        }
    }
}

程序运行的截图如下所示:

  • 3.使用class建立对象:
    如果知道类的名称,可以使用new关键字建立实例,如果事先不知道类的名称,我们可是使用class.forName()动态加载.class文件,在取得方法后再利用其newInstance来取得实例。这种方法在书中用电影拍摄放映的例子很好的进行了解释。首先,我们先定义出影片链接库该有的功能:
package cc.openhome;

public interface Player {
    void play(String video);
}

然后,可以先完成动画的操作播放:

package cc.openhome;

import java.util.Scanner;

public class MediaMaster {
    public static void main(String[] args) throws ClassNotFoundException, 
                            InstantiationException, IllegalAccessException {
        String playerImpl = System.getProperty("cc.openhome.PlayerImpl");
        Player player = (Player) Class.forName(playerImpl).newInstance();
        System.out.print("输入想播放的影片:");
        player.play(new Scanner(System.in).nextLine());
    }
}

在上面的类名称中,并没有把Player的类定义的很固定,这可以再启动程序时通过系统属性来指定,其操作如下:

package cc.openhome;

public class ConsolePlayer implements Player {
    @Override
    public void play(String video) {
        System.out.println("正在播放 " + video);
    }
}
    
建立ClassLoder实例:

JVM的ClassLoader分三层,分别为Bootstrap ClassLoaderExtension ClassLoaderSystem ClassLoader,他们不是类继承的父子关系,是逻辑上的上下级关系。
Bootstrap ClassLoader是启动类加载器,它是用C++编写的,从%jre%/lib目录中加载类,或者运行时用-Xbootclasspath指定目录来加载。
Extension ClassLoader是扩展类加载器,从%jre%/lib/ext目录加载类,或者运行时用-Djava.ext.dirs制定目录来加载。
System ClassLoader,系统类加载器,它会从系统环境变量配置的classpath来查找路径,环境变量里的.表示当前目录,是通过运行时-classpath或-Djava.class.path指定的目录来加载类。
下面有个简单的范例可以指定加载路径,测试class实例是否为同一对象:

package Reflection;



        import static java.lang.System.out;
        import java.net.MalformedURLException;
        import java.net.URL;
        import java.net.URLClassLoader;

public class ClassLoaderDemo {
    public static void main(String[] args) {
        try {
            String path = args[0];    
            String clzName = args[1]; 

            Class clz1 = loadClassFrom(path, clzName);
            out.println(clz1);
            Class clz2 = loadClassFrom(path, clzName);
            out.println(clz2);

            out.printf("clz1 与 clz2 为%s实例",
                    clz1 == clz2 ? "相同" : "不同");
        } catch (ArrayIndexOutOfBoundsException e) {
            out.println("沒有指定类别加载路径与名称");
        } catch (MalformedURLException e) {
            out.println("载入路径错误");
        } catch (ClassNotFoundException e) {
            out.println("找不到指定的类別");
        }
    }

    private static Class loadClassFrom(String path, String clzName)
            throws ClassNotFoundException, MalformedURLException {
        ClassLoader loader = new URLClassLoader(new URL[] {new URL(path)});
        return loader.loadClass(clzName);
    }
}

程序的截图如下:

十八章:

  • 1.自定义泛型:
    泛型的本质就是将数据类型也参数化, 普通方法的输入参数的值是可以变的,但是类型(比如: String)是不能变的,它使得了在面对不同类型的输入参数的时候我们要重载方法才行。泛型就是将这个数据类型也搞成跟参数的值一样可以变。
  • 2.自定义枚举:
    枚举是一种规范它规范了参数的形式,这样就可以不用考虑类型的不匹配并且显式的替代了int型参数可能带来的模糊概念 枚举像一个类,又像一个数组。Enum作为Sun全新引进的一个关键字,看起来很象是特殊的class, 它也可以有自己的变量,可以定义自己的方法,可以实现一个或者多个接口。枚举具有如下特性:
    1.它不能有public的构造函数,这样做可以保证客户代码没有办法新建一个enum的实例。
    2.所有枚举值都是public , static , final的。注意这一点只是针对于枚举值,我们可以和在普通类里面定义 变量一样定义其它任何类型的非枚举变量,这些变量可以用任何你想用的修饰符。
    3.Enum默认实现了java.lang.Comparable接口。
    4.Enum覆载了了toString方法,因此我们如果调用Color.Blue.toString()默认返回字符串”Blue”.
    5.Enum提供了一个valueOf方法,这个方法和toString方法是相对应的。调用valueOf(“Blue”)将返回Color.Blue.因此我们在自己重写toString方法的时候就要注意到这一点,一把来说应该相对应地重写valueOf方法。
    6.Enum还提供了values方法,这个方法使你能够方便的遍历所有的枚举值。
    7.Enum还有一个oridinal的方法,这个方法返回枚举值在枚举类种的顺序,这个顺序根据枚举值声明的顺序而定,这里Color.Red.ordinal()返回0。

本周代码托管截图

本周代码链接

本周代码统计截图

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 100/300 1/3 18/38
第三周 200/500 1/4 22/60
第四周 250/750 1/5 30/90
第五周 450/1200 1/6 20/110
第六周 400/1600 2/8 30/140
第七周 150/1750 2/10 30/170
第八周 500/2250 2/12 30/200
第九周 230/2580 2/14 30/230

参考资料

posted @ 2016-05-02 09:29  20145107lcd  阅读(203)  评论(1编辑  收藏  举报