java基础复习(集合、泛型、IO流、多线程、Junit 、内省 、Properties、 路径问题)

  • 集合
  • 泛型
  • IO流
  • 多线程
  • Junit
    • Assert
    • 注解
  • 内省
  • Properties
  • 路径问题

集合

---|Collection: 单列集合
    ---|List: 有存储顺序, 可重复
        ---|ArrayList:  数组实现, 查找快, 增删慢
                                由于是数组实现, 在增和删的时候会牵扯到数组
增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快
        ---|LinkedList: 链表实现, 增删快, 查找慢由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高但查询时需要一个一个的遍历, 所以效率较低
        ---|Vector: 和ArrayList原理相同, 但线程安全, 效率略低
 和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低
    ---|Set: 无存储顺序, 不可重复
        ---|HashSet   线程不安全,存取速度快。底层是以哈希表实现的。
        ---|TreeSet   红-黑树的数据结构,默认对元素进行自然排
                            序(String)。如果在比较的时候两个对象
                            返回值为0,那么元素重复。
---| Map: 键值对   键不可重复,键可以重复
    ---|HashMap    线程不安全,存取速度快。底层是以哈希表实现的.
    ---|TreeMap   红-黑树的数据结构,默认对元素进行自然排
            序(String)。如果在比较的时候两个对象
             返回值为0,那么元素重复
    ---|HashTable  底层也是使用了哈希表 维护的,存取的读取快,存储元素是
                     无序的。

泛型

  1. 泛型类型必须是引用类型
  2. 使用泛型方法前需要进行泛型声明,使用一对尖括号 <泛型>,声明的位置在static后返回值类型前。
  3. 当一个类中有多个函数声明了泛型,那么该泛型的声明可以声明在类上。

函数泛型:

public <T> T getData(T data) {
        return data;
}

类泛型:

public class Demo6<T> {
    public static void main(String[] args) {
        System.out.println(getData2(100));
    }

    public T getData(T data) {
        return data;
    }

    //静态方法不可以使用类中定义的泛型,错误
    public static T getData2(T data) {
        return data;
    }

}
  1. 创建对象的时候要指定泛型的具体类型
  2. 创建对象时可以不指定泛型的具体类型(和创建集合对象一眼)。默认是Object,例如我们使用集合存储元素的时候没有使用泛型就是那么参数的类型就是Object
  3. 类上面声明的泛型只能应用于非静态成员函数,如果静态函数需要使用泛型,那么需要在函数上独立声明(加T)。
  4. 如果建立对象后指定了泛型的具体类型,那么该对象操作方法时,这些方法只能操作一种数据类型。
  5. 所以既可以在类上的泛型声明,也可以在同时在该类的方法中声明泛型。

IO流

读文件:

public static void main(String[] args) {
    String path = "c:/a.txt";
    FileInputStream in = null;
    try {
        // 打开流
        in = new FileInputStream(path);
        // 使用流读文件内容
        int b = in.read();
        while (b != -1) {
            System.out.print((char) b);
            b = in.read();
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally {
        // 释放资源
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

拷贝文件

public static void main(String[] args) {
    String srcPath = "c:/a.txt";
    String destPath = "c:/b.txt";

    // 一定要使用字节流
    InputStream in = null;
    OutputStream out = null;
    try {
        // 打开流
        in = new FileInputStream(srcPath);
        out = new FileOutputStream(destPath);
        // 使用流
        byte[] buf = new byte[1024 * 8];
        for (int len = -1; (len = in.read(buf)) != -1;) {
            out.write(buf, 0, len);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 释放资源
        try {
            if (in != null) {
                in.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

多线程

两种启动线程方法:

private static int count = 100;

public static void main(String[] args) {
    // 用继承Thread类的方式启动一个线程
    new Thread() {
        public void run() {
            synchronized (StartThreadTest.class) {
                while (count > 0) {
                    count--;
                    System.out.println(Thread.currentThread() + "卖了一张票,还剩" + count);
                }
            }
        }
    }.start();

    // 用实现Runnable接口的方式启动一个线程
    new Thread(new Runnable() {
        public void run() {
            synchronized (StartThreadTest.class) {
                while (count > 0) {
                    count--;
                    System.out.println(Thread.currentThread() + "卖了一张票,还剩" + count);
                }
            }
        }
    }).start();
}

Junit

一、搭建环境:

导入junit.jar包(junit4)

二、写测试类:

0. 一般一个类对应一个测试类。

1. 测试类与被测试类最好是放到同一个包中(可以是不同的源文件夹)

2. 测试类的名字为被测试类的名字加Test后缀。

三:写测试方法:

0. 一般一个方法对应一个单元测试方法。

1. 测试方法的名字为test前缀加被测试方法的名字,如testAddPerson()。

2. 单元测试方法上面要加上@Test注解(org.junit.Test)!

3,单元测试方法不能有参数,也不能有返回值(返回void)!测试的方法不能是静态的方法。

四、测试方法的基本使用:

1. 可以单独执行一个测试方法,也可以一次执行所有的、一个包的、一个类中所有的测试方法。

2. 执行完后,显示绿色表示测试成功;显示红色表示测试失败(抛异常后会测试失败)。

Assert

assertTrue(...)     参数的值应是true
assertFalse(...)    参数的值应是false  

assertNull(...)     应是null值
assertNotNull(...)  应是非null的值

assertSame(...)     使用==比较的结果为true(表示同一个对象)
AssertNotSame(...)  使用==比较的结果为false

assertEquals(...)   两个对象equals()方法比较结果为true

注解:

@Test
    表示单元测试方法。

@Before
    所修饰的方法应是非static的(且没有参数,返回值为void)。
    表示这个方法会在本类中的每个单元测试方法之前都执行一次。

@After
    所修饰的方法应是非static的(且没有参数,返回值为void)。
    表示这个方法会在本类中的每个单元测试方法之后都执行一次。

@BeforeClass
    所修饰的方法应是static的(且没有参数,返回值为void)。
    表示这个方法会在本类中的所有单元测试方法之前执行,只执行一次。

@AfterClass
    所修饰的方法应是static的(且没有参数,返回值为void)。
    表示这个方法会在本类中的所有单元测试方法之后执行,只执行一次。

内省

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。

问题一: 什么是Java对象的属性和属性的读写方法?

问题二: 如何通过内省访问到javaBean的属性 ?

1.通过PropertyDescriptor类操作Bean的属性.

public static void testPropertyDescriptor() throws Exception{
        Person p = new Person();
        PropertyDescriptor propertyDescriptor =  new PropertyDescriptor("id",Person.class);
        //获取属性的写的方法。
        Method writeMethod = propertyDescriptor.getWriteMethod();
        Method readMethod = propertyDescriptor.getReadMethod();
        propertyDescriptor.getReadMethod();
        writeMethod.invoke(p, 12);
        System.out.println(readMethod.invoke(p, null));
    }

2.通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。

public static void testIntrospector() throws Exception{
        BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
        PropertyDescriptor[]  descriptor = beanInfo.getPropertyDescriptors();
        for(PropertyDescriptor itemProperty : descriptor){
            System.out.println(itemProperty.getReadMethod().getName());
        }
    }

存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。

public static void main(String[] args) throws Exception {
        Person p = new Person();
        ConvertUtils.register(new Converter() {

            @Override
            public Object convert(Class type, Object value) {
                 try {
                    if(value!=null){

                         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");
                         Date d = dateFormat.parse((String) value);
                         return d;
                     }
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                return null;
            }
        }, Date.class);

        BeanUtils.setProperty(p,"id","110");
        BeanUtils.setProperty(p,"name","狗娃");
        BeanUtils.setProperty(p, "birthDay","1992 12 12");
        System.out.println(p.getId() +"=="+ p.getName()+"======"+p.getBirthDay());
    }

Properties

Properties类对应.properties文件。文件内容是键值对,键值对之间使用”=”或空格隔开。开头是”#”的表示注释

Properties类在加载.properties文件时使用的iso8859-1的编码。所以这个文件中的中文要特殊处理:如果这个配置文件中有中文就必须要进行转义,使用native2ascii.exe命令操作:

native2ascii d:/my.properties d:/my2.properties

使用Properties类中的load(InputStream) 方法可以加载配置文件,使用其中的store(OutputStream) 方法可以保存配置到指定文件。

加载:

public static void testLoadProperties() throws Exception {
    Properties properties = new Properties();

    InputStream in = new FileInputStream("E:/itcast/config.properties");
    properties.load(in); // 加载
    in.close();

    System.out.println(properties);
}

写配置文件:

public static void testStoreProperties() throws Exception {
    // 准备配置信息
    Properties properties = new Properties();
    properties.setProperty("name", "李四");
    properties.setProperty("age", "20");

    // 准备
    OutputStream out = new FileOutputStream("d:/my.properties");
    String comments = "这是我的配置文件";

    // 写出去
    properties.store(out, comments);
    out.close();
}

案例:使用properties读取配置文件,读取数据库的用户名、密码

public class DBUtil {

    static Properties properties = new Properties();

    static{
        try {
            Class clazz = DBUtil.class;
            InputStreamReader fileReader =
            new InputStreamReader(clazz.getResourceAsStream("/db.properties"));
            properties.load(fileReader);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static String getUserName(){
        String userName =properties.getProperty("userName");
        return userName;
    }

    public static String getPassword(){
        return  properties.getProperty("password");
    }
    public static void main(String[] args) {
        System.out.println("用户名:"+ getUserName());
        System.out.println("密码: "+  getPassword());
    }
}

路径问题

绝对路径的问题: 比如C:\abc\a.properties文件路径,该路径在windows上执行没有 问题,但是如果把该项目移动到linux上面执行 ,该路径就会出现问题了,因为在linux上面没有c盘的,只有根目录\。

相对路径存在的问题:相对路径是相对于目前执行class文件的时候,控制台所在的路径,这样子也会导致出现问题。

在Java程序中使用File时写相对路径,是指相对于执行java命令时当前所在的文件夹。

public class PathTest {
    public static void main(String[] args) throws Exception {
        System.out.println(new File("a.txt").getAbsolutePath());
    }
}

获取classpath中的资源(InputStream)

public static void main(String[] args) throws Exception {
    Class clazz = new ClassPathTest().getClass();

    // 开头的‘/‘表示classpath的根目录,这个是表示从classpath的根目录中开始查找资源
    InputStream in = clazz.getResourceAsStream("/cn/itcast/my.properties");

    // 如果开头没有‘/‘,表示从当前这个class所在的包中开始查找
    InputStream in2 = clazz.getResourceAsStream("my.properties");
}
时间: 2024-12-15 15:37:21

java基础复习(集合、泛型、IO流、多线程、Junit 、内省 、Properties、 路径问题)的相关文章

Java基础知识强化之IO流笔记66:Properties的概述 和 使用(作为Map集合使用)

1. Properties的概述  Properties:属性集合类.是一个可以和IO流相结合使用的集合类.Properties 可保存在流中或从流中加载.属性列表中每个键及其对应值都是一个字符串. Properties是Hashtable的子类,说明是一个Map集合. 2. Properties作为Map集合使用 1 package cn.itcast_08; 2 3 import java.util.Properties; 4 import java.util.Set; 5 6 /* 7 *

Java基础知识强化之IO流笔记68:Properties和IO流集合使用

1. Properties和IO流集合使用 这里的集合必须是Properties集合:  public void load(Reader reader):把文件中的数据读取到集合中  public void store(Writer writer,String comments):把集合中的数据存储到文件 2. 代码实现: 1 package cn.itcast_08; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 i

Java基础知识强化之IO流笔记69:Properties练习之 判断文件中是否有指定的键,如果有就修改值的案例

1. 我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么. 请写一个程序判断是否有"lisi"这样的键存在,如果有就改变其值为"100"  分析:  A:把文件中的数据加载到集合中  B:遍历集合,获取得到每一个键  C:判断键是否有为"lisi"的,如果有就修改其值为"100"  D:把集合中的数据重新存储到文件中 2. 代码实现: 1 package cn.itcast_08; 2 3 i

Java 基础(四)| IO 流之使用文件流的正确姿势

为跳槽面试做准备,今天开始进入 Java 基础的复习.希望基础不好的同学看完这篇文章,能掌握泛型,而基础好的同学权当复习,希望看完这篇文章能够起一点你的青涩记忆. 一.什么是 IO 流? 想象一个场景:我们在电脑上编辑文件,可以保存到硬盘上,也可以拷贝到 U 盘中.那这个看似简单的过程,背后其实是数据的传输. 数据的传输,也就是数据的流动.既然是流动也就会有方向,有入方向和出方向.举个上传文件的栗子,现在有三个对象,文件.应用程序.上传的目标地址(服务器).简化的上传文件有两步: 应用程序读文件

Java 基础(三)| IO流之使用 File 类的正确姿势

为跳槽面试做准备,今天开始进入 Java 基础的复习.希望基础不好的同学看完这篇文章,能掌握泛型,而基础好的同学权当复习,希望看完这篇文章能够起一点你的青涩记忆. 一.什么是 File 类? java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 二.File 类的使用 2.1 构造方法 File 类的构造有三种: public File(String pathname) : 直接通过文件路径字符串创建 public File(String par

Java基础知识回顾之六 ----- IO流

前言 在上一篇文章中,回顾了Java的多线程.而在本篇文章中主要介绍Java IO的相关知识. IO的介绍 什么是IO? IO的名称又来是Input与Output的缩写,也就是输入流和输出流.输入流用于从源读取数据,输出流用于向目标写数据. 可以从下列示例图来了解IO流: IO流使用 IO流对文件的操作主要分为字符流和字节流. 字符流 字符流有两个抽象类:Writer和Reader类.其对应子类FileWriter和FileReader可实现文件的读写操作.BufferedWriter和Buff

java基础学习笔记之IO流

1.IO流用来处理设备之间的数据传输方向:硬盘通过“读reader”完成对内存的读取,内存通过“写writer”完成对硬盘的写入2.Java对数据的操作是通过流的方式3.Java用于操作流的对象都在IO包中4.流按操作数据分为两种:字节流和字符流--字符流的由来:>>字节流读取文字字节数据后,不直接操作而是先查指定的编码表.获取对应的文字.再对这个文字进行操作.简单说:字符流=字节流+编码表--字节流的两个顶层父类:1.InputStream 2.OutputStream--字符流的两个顶层父

黑马程序员--Java基础学习笔记【IO流-字节流、转换流】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- IO 流 常用基类 字节流 InputStreamOutputStream 常用方法 int read() // 读取一个字节,以 int 形式返回 intread(byte[] b) // 读取最多数组长度个字节并存入该数组,返回实际读取字节 void write(int d) // 写出一个字节 voidwrite(byte[] d) // 将给定字节数组中的所有字节全部写出 void w

Java基础知识强化之IO流笔记16:IO流的概述和分类

1. IO流的分类   流向:     (1)输入流:读取数据到内存     (2)输出流:写入数据到硬盘(磁盘)   操作的数据类型:    (1)字节流:操作的数据是字节                            输入流                            输出流        (2)字符流:操作的数据是字符,为了方便操作文本数据,Java就提供了字符流.                            输入流                      

Java基础知识强化之IO流笔记17:FileOutputStream构造方法使用

1. 可以参照之前写的笔记:   Android(java)学习笔记167:Java中操作文件的类介绍(File + IO流) 2. FileOutputStream(常用的)构造方法: FileOutputStream(File file)           Constructs a new FileOutputStream on the File file. FileOutputStream(String filename)           Constructs a new FileO