java基础复习(二)

JAVA基础(二)


一、数据结构

1、概述

数据结构(data structure):是计算机专业一门独立学科,主要研究数据的逻辑结构、存贮结构以及数据之间的关系

什么是数据:

  • 在计算机系统中,各种字母和数字符号的组合、语音、图形、图像等统称为数据
  • 又指所有能输入计算机并且被计算机程序处理的符号的总称,是用于输入计算机进行处理,具有一定意义的数字、字母、符号和模拟量的统称

逻辑图如下:

2、数据结构

1.逻辑结构

集合

一个存放数据的容器,数据元素间没有任何关系

线性结构

数据元素间有线性关系,分为线性表、队列、栈和串

线型关系:除第一个元素外,其他元素有且只有一个前驱,除最后一个元素外,其他元素有且只有一个后继

树结构

数据元素间有层状关系,例如二叉树

图结构

数据元素间有网状关系

2.存储结构

顺序存储结构

数据存放在磁盘连续的空间中

链式存储结构

数据存放在磁盘的任何位置,单向链式存贮(单链表)、双向链式存贮(双链表)、循环链式存贮(循环链表)

3、线性结构

1、线性表

基于数组实现线性结构 ,用数组存放数据,并保持元素之间是一个线性关系

编写线性结构的数据结构:

public void insert(int i,Object data);  // 添加到线性表指定的位置;
public void append(Object data);  // 追加到线性表的末尾;
public void remove(int i);  // 移除元素
public void update(int i,Object data);  // i为下标 ;
public Object get(int i);  // 获取元素
public Object[] list();
public int size();  // 线性表元素数量;
public boolean isEmpty();  // 线性表是否为空;

对数据常见操作:检索,插入,删除,更新,排序

2、栈(stack)

常用方法:

public void push(Object data);  // 添加元素
public Object pop();  // 取出元素并删除
public Object seek();  // 取出元素不删除
public int size();  // 元素数量
public boolean isEmpty();  // 判断栈是否为空
3、队列(queue)

队列特点:先进先出(FIFO)

常用方法:

boolean offer(E e);  // 添加数据
Object poll();   // 删除出队
Object peek();  // 返回队列第一次元素(不删)
int size();  // 元素数量
boolean isEmpty();  // 判断队列是否为空
4、串

串:即字符串(String),是由零个或多个字符组成的有限序列。一般表示为s=“c1,c2,c3...cn”

子串:串中任意个连续的字符组成的子序列

主串:包含子串的串

空串:n=0的串

空格串:值为空格的串

4、树结构

树是一种非线性的数据结构,由n(n>0)个有限结点组成的具有层次关系的集合。

树有一个特殊的结点,叫根结点,根结点没有前驱结点。

树形结构中,子树之间不能有交集。

树的性质如下:

  • 每个子树有且只有一个前驱结点
  • 每个子树的根结点可以有0或多个后继结点
  • 数是递归的
  • 一个n个结点的数有n-1条边

5、图结构

图结构是比线性表和树结构更为复杂的数据结构。

树结构中,子树之间不能有交集,但在图结构中,是可以有交集的。

图结构中有顶点和边

顶点:图中的数据元素

边:图中连接顶点的线

所有的顶点组成一个顶点集合,所有的边组成一个边集合,组合在一起就是一个图结构

无向图:在一个图中,如果所有的边都没有方向,则称之为无向图

有向图:在一个图中,边有方向,则称之为有向图

混合图:一个图中,边同时有有向和无向的图

二、异常处理

1、理解异常

程序在运行过程中出现的问题称为异常(Exception),出现异常时的处理叫异常处理

JAVA的异常分为:

  • Error:java应用程序本身无法恢复的严重错误,程序不需要捕获、处理这些严重错误
  • Exception:java程序抛出和处理的非严重异常,分为运行时异常(RuntimeException)和检查异常(CheckException),也称非运行时异常

所有的异常都继承至java.lang.Throwable

Throwable
    ---- Error
    ---- Exception 
    	---- RuntimeException
    	---- CheckException

2、Exception

需要程序员处理的,如果此类异常被捕获,程序在运行时是不会崩溃的,如果没有捕获(不做异常处理),可能导致整个程序运行崩溃

Exception异常分为2类:

  • 运行时异常:正常编译,但程序运行时出的问题,又称为非检查异常
  • 检查异常:此异常是在编写代码时就会以红色波浪线提示,需要做异常处理,又称非运行时异常

常见的运行时异常:

java.lang.ArrayIndexOutOfBoundsException:数组的下标越界异常
java.lang.ArithmeticException:数学运算异常
java.lang.NullPointerException:空指针异常
java.lang.ClassCastException:类型转换异常
java.lang.NumberFormatException:数字格式化异常
java.util.InputMismatchException:输出信息类型不匹配异常

常见的检查异常:

java.io.FileNotFoundException:文件找不到异常 
java.io.IOException:输入输出异常
java.lang.NoSuchMethodException:方法未找到异常

3、异常处理

异常处理的三种结构:

try…catch

try{
    //可能出现异常语句块
}catch(SomeException e){// 特指某些特定的异常
    //当捕获到SomeException类型的异常时执行的语句块,通常是打印该异常信息
}

catch语句可以多个,但如果是Exception类型来捕获,必须为最后一个catch

如果try语句块中的代码没有异常,则try语句块执行完毕后,catch中的语句块不执行;如果try语句块有异常,则try语句块中发生异常之后的代码不执行,而由相应的catch语句进行捕获,catch中的代码会执行

try…catch…finally

try {
    //可能抛出异常的语句块
}catch(SomeException e){
    //当捕获到异常时运行的语句块
}finally {
    //不管是否发生异常都会执行的语句块
}

finally是异常处理最后一个语句块,可加可不加,不管异常有没有发生,此语句块都会执行,finally语句块一般做的操作为资源释放,关闭流,关闭数据库连接等

try…finally

try {
    //可能抛出异常的语句块
}finally {
    //不管是否发生异常都会执行的语句块
}

异常处理中,唯一不执行finally语句块的一种情况是在catch语句中出现System.exit(1)的代码,则直接退出jvm,finally语句块不执行

注意事项:

  • 应按照从小到大的顺序捕获异常,即应先写具体的异常类型,最后再写他们的父类Exception类型的异常
  • 当try语句中有多个异常时,只会捕获第一个异常,异常后面的代码不会执行
  • 捕获异常时尽量不要用return语句
  • 当try/catch语句块中出现return时,先执行return语句之前的代码,再执行finally语句块,最后执行return

4、throw与throws

throw:手动抛出异常

语法:throw 异常对象

throw new Exception("异常信息...........");
throw new MyException("自定义异常.........")

throws:声明异常

在定义方法时,同时给方法声明一个异常

public void insert(int i, Object data) throws Exception{
    if(i < 0){
        throw new Exception("下标不合法");
    }
}

通过throws声明异常后,若调用该方法,则需要处理该异常

public void insert(int i, Object data) throws Exception{
    if(i < 0){
        throw new Exception("下标不合法");
    }
}

public void add(int i, Object data){
    // 需要处理异常
    try{
        insert(i, data);
    } catch(Exception e){
        
    }
}

所有声明式异常都是检查异常,在编码时,就需要处理,否则语法出错

throw和throws可以同时出现,也可以单独出现,当throw单独出现时,可将throw语句放入try语句中直接进行异常处理;当throws单独出现时,可直接加在方法后面

5、自定义异常

自己写一个异常类型,处理特定异常问题

自定义异常需要继承Throwsable类或者Exception类(通常继承此类)

public class UserException extends Exception{
	public UserException(String messgae) {
		super(messgae);
	}
}

做完自己的异常类后,在需要异常的方法中就可以通过throw语句来抛出该异常,抛出的异常可以直接throws掉让调用方处理或者直接try...catch

public static void main(String[] args) throws Exception{
    int i = 5;
    if (i > 0){
        throw new MyException("错误");
    }
}

// 或者
public static void main(String[] args){
    int i = 5;
    if (i > 0){
        try {
            throw new MyException("错误");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}

throw 与 throws区别

throw为手动抛出异常,指运行到该语句就抛出异常,不往下执行,或者可以通过try...catch处理该异常,例如打印日志和异常堆栈信息

throws为声明式异常,在定义时,在方法的后面通过throws 指定异常类型,此时,调用该方法必须去处理该异常

三、集合与泛型

集合结构图

1、集合

集合对象是内存中的一个容器对象,用来方便的存贮批量的数据,集合中的数据在没有持久化,程序运行结束后,数据将消失。在java语言中,设计的集合主要为3大类

  • Set集合:实现Set接口的集合类称为Set集合;

  • List集合:实现List接口的集合类称为List集合;

  • Map集合:实现Map接口的集合类称为Map集合

java对集合设计的相关接口与类放在:java.util包中,在我们使用集合时,需要导入对应的集合类或者接口

集合中只能放引用类型数据,不能放基本数据类型,如果要放,请使用基本数据类型的包装类型

Collection是Set、List、Queue三个集合共同的接口

2、Set集合

Set集合特性:不包含重复元素,通过调用元素的equals方法实现判断两个元素是不是同一个元素

public interface Set<E> extends Collection<E>

Set接口的实现类:HashSet、TreeSet

1.HashSet

基于hash算法决定元素在集合中的存放位置,HashSet存取效率非常高

熟练Set集合的基本操作API:添加、删除、获取元素、集合大小,清空集合等

获取集合元素:

1、转成数组

Set set = new HashSet();
set.add(1);
set.add(2);
set.add(3);
Object[] arr = set.toArray();
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

2、迭代器(Iterable)

迭代器:

  • 一个递归获取集合元素的方式 ,需要集合实现Iterable接口,此接口定义了迭代访问集合元素的方法
  • 迭代器是一个指针对象,默认指向集合第一个元素前,通过调用hashNext()方法可以移动迭代器
// 迭代器:Iterable
Iterator<T> iterator(); // 实现Iterable接口的方法,就能得到的一个迭代器对象

// Iterator的主要方法
boolean hasNext();  // 如果仍有元素可以迭代,则返回true
E next();  // 返回迭代的下一个元素
void remove(); // 从迭代器指向的collection中移除迭代器返回的最后一个元素

// 通过迭代器获取Set集合元素
Set set = new HashSet();
set.add(1);
// ....
Iterator it = set.iterator();
while(it.hasNext()) {
    System.out.println(it.next());
}

对Set集合,如果放到集合里的是一个对象,且当对象的某个属性一致时,判断为同一个属性,如何操作?

Set集合默认是调用对象的equals方法比较,此时,已不能满足我们的业务需要

解决方法:根据新的业务重写equals方法, 此时还要重写hashcode方法

下面的例子是当tel相同时视为同一个对象:

User类:

@Data
public class User {

    private int id;

    private String name;

    private String tel;

    @Override
    public int hashCode(){
        // 这里重写了hashCode方法,将tel作为hashCode的值
        return Integer.parseInt(tel);
    }

    @Override
    public boolean equals(Object o){
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        User user = (User) o;
        // 根据Tel是否相同判断是否为同一个人
        if (tel.equals(user.getTel())) {
            return true;
        }
        return Objects.equals(id, user.id);
    }
}

测试:

public static void main(String[] args){
    Set set = new HashSet();

    User u1 = new User();
    u1.setId(1);
    u1.setName("张三");
    u1.setTel("183");

    User u2 = new User();
    u2.setId(2);
    u2.setName("李四");
    u2.setTel("183");

    set.add(u1);
    set.add(u2);

	// 可以看到,只输出了1,证明只有1个对象存进去了
    System.out.println(set.size());

    Iterator it = set.iterator();
    while (it.hasNext()){
        System.out.println(it.next());
    }

}
2.TreeSet

Set接口的第2个实现类,TreeSet相对于HashSet,多了一个排序的功能

排序方法:使用元素的自然顺序对元素进行排序

元素的自然顺序:此元素实现Comparable接口,当将元素放到TreeSet集合中,TreeSet集合就根据Comparable接口定义的比较规则来比较元素

// 返回值为整型: 为0 表示两个元素相等,大于0 表示大于,小于0 表示小于
public interface Comparable{
  int compareTo(T o)  
}

如果放到TreeSet集合中的元素没有实现自然排序,则意味会出异常。在JDK中,8种基本数据类型的包装类型和字符串都实现了此接口

如果在集合中放其它类型的元素,必须手动实现Comparable接口,并实现接口中定义的compareTo方法

@Data
public class User implements Comparable<User>{

    private int id;

    private String name;

    private String tel;

    @Override
    public int compareTo(User o) {
        // 根据id排序
        int compare = Integer.compare(this.id, o.getId());
        if (compare == 0) {
            // 若id相同,则根据名字排序
            return this.name.compareTo(o.getName());
        }
        return compare;
    }
}
3.Set集合的一些方法
  • boolean add(Object obj);:添加元素,不能重复,如果重复,则添加无效
  • void clear();:清空集合
  • boolean contains(Object obj);:判断集合中是否包含此元素
  • boolean isEmpty();:判断是否为空
  • Iterator iterator();:返回一个迭代器对象
  • boolean remove(Object obj);:删除元素
  • int size();返回元素个数:返回元素个数
  • Object[] toArray();:返回一个数组

3、List集合

特性:实现List接口的集合称为List集合,相对Set集合,List集合中的元素是有序的,每一个元素都有一个下标,从0开始

List集合可以放重复数据

List集合的主要实现:ArrayList,Vector,LinkedList (三个实现类的API基本一样)

public interface List<E> extends Collection<E>

ArrayList

又称为动态数组,ArrayList内部是使用数组来存放数据的,当容器添加满,会自动扩容,每次扩容至原来的1.5倍

ArrayList是线程非安全的

ArrayList对于添加、获取数据效率是比较高的

Vector

线程安全

LinkedList

LinkedList使用链表来存放数据

LinkedList对于删除、修改数据效率比较高

List集合的一些方法:

  • void add(int index, Object o);:在集合的指定位置插入元素
  • Object get(int index);:获取指定位置的元素
  • int indexOf(Object o);:返回该元素第一次出现的下标
  • int lastIndexOf(Object o);:返回该元素最后一次出现的下标
  • Object remove (int index);:删除指定位置的元素
  • Object set(int index, Object o);:用该元素替换该位置的元素

4、Map集合

Set集合与List集合都属于单例值的集合,Map集合是双列值的集合,即集合中每一个元素是一个key - value对象,根据key可以取出对应键value的值

key - value 称为Entry对象

不能包含重复的键,每个键最多只能映射到一个值

Map集合的主要实现:HashMap、TreeMap、Hashtable、Properties

HashMap

集合中的key可以为null,值也可以为null,但只能有一个key为null,HashMap是线程非安全的

TreeMap

相对于HashMap,多了一个排序的功能,与TreeSet类似

HashTable

键和值都不能为空的,是线程安全的

Properties

Properties是一种属性文件,后缀为.properties,通常用于存储配置

该文件以key - value保存内容,格式为key=value

如何通过Map.Entry遍历Map集合:

Map<String, String> map = HashMap<>();
for(Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " - " + entry.getValue());
}

Map集合的一些方法:

  • Object put(Object key, Object value);;将指定键值添加到集合中,若与前面的相同,则替换
  • Object get(Object key);:返回指定键所对应的值
  • Object remove(Object key);:通过指定的键删除该键值对
  • Set keySet();:返回此Map集合中包含的键的Set集合
  • Collection values();:返回此Map集合中包含的值的Collection集合
  • int size();:返回集合的键值对的个数

5、内部比较器与外部比较器

比较器:用于集合的排序,当集合需要排序时,就需要用到比较器

内部比较器:在一个类中实现了Comparable接口,也就是在类的内部实现比较规则,称为内部比较器

外部比较器: 单独写一个类,实现比较,需要实现一个新的接口java.util.Comparator,外部比较器一般在集合的工具类java.util.Collections中使用

Collections工具类:主要服务于Set集合与List集合,Collections工具类中的方法一般为静态方法

使用比较器对List集合的元素排序

外部比较器实现:

// 创建一个比较器
public class MyComparator implements Comparator<User> {

    @Override
    public int compare(User o1, User o2) {
        // 根据id排序,调用Integer的compareTo()方法
        return o1.getId().compareTo(o2.getId());
    }

}

public static void main(String[] args){
        
    List<User> list = new ArrayList<>();

    User u1 = new User();
    u1.setId(2);
    u1.setName("张三");
    u1.setTel("183");

    User u2 = new User();
    u2.setId(1);
    u2.setName("李四");
    u2.setTel("183");

    list.add(u1);
    list.add(u2);

    // 使用sort方法排序
    Collections.sort(list, new MyComparator());
    for (User user : list) {
        System.out.println(user);
    }

}

内部比较器实现:

// User类实现Comparable接口,并实现compareTo方法
@Data
public class User implements Comparable<User>{

    private Integer id;

    private String name;

    private String tel;

    @Override
    public int compareTo(User o) {
        // 根据id排序
        int compare = Integer.compare(this.id, o.getId());
        if (compare == 0) {
            // 若id相同,则根据名字排序
            return this.name.compareTo(o.getName());
        }
        return compare;
    }
}

public static void main(String[] args){

    List<User> list = new ArrayList<>();

    User u1 = new User();
    u1.setId(2);
    u1.setName("张三");
    u1.setTel("183");

    User u2 = new User();
    u2.setId(1);
    u2.setName("李四");
    u2.setTel("183");

    list.add(u1);
    list.add(u2);

    // 使用sort方法排序
    Collections.sort(list);
    for (User user : list) {
        System.out.println(user);
    }

}

6、泛型(Generic Type)

泛型:一个待确定的类型(类型占位符),在设计时用泛型,在使用时,需要给定一个确定的类型,如果不明确指定,默认类型为Object

集合中用到泛型:泛型集合

普通的类中用到泛型:泛型类

方法中用到泛型:泛型方法

接口中用到泛型:泛型接口

泛型的优点:在使用时,会用语法检查,避免添加错误类型的数据

通配符

<?>:无界通配符

List<?> list = new ArrayList<a>();

a可以是任意类型

<? extends E>:上界通配符

List<? extends E> list = new ArrayList<a>();

此时a可以是E或者E的子类类型,参数列表中如果有多个类型参数上限,用逗号分开

< ? super E>:下界通配符

List<? super E> list = new ArrayList<a>();

此时a可以是E或者E的父类

泛型 ? 通配符与T作用

T 是一个 确定的类型,通常用于泛型类和泛型方法的定义,?是一个不确定 的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。例如List<E>表示集合里是E类的实例,List<?>表示集合里的对象类型不确定,与List一样。

四、IO流与XML

1、IO概述

IO:分为:Input与Output

Input:输入,将磁盘中的文件读到内存中

Output:输出,将内存中的数据写入磁盘

Stream:流,将磁盘中的静态字节数据变成流动中的字节数据

文件进行读写的操作的所有接口与类放在:java.io包中

2、File类

探测文件(文件夹)的信息,再进一步对文件(文件夹)进行操作

File:获取文件的信息、创建、删除、重命名、移动等操作

对目录:提供删除、创建目录以及获取目录下所有文件和文件夹等

常见方法

1.对文件

  • getPath():获取文件路径
  • getName():获取文件名
  • length():获取文件大小
  • createNewFile():创建一个文件
  • renameTo():重命名
  • isFile():判断是否为文件

2.对文件夹

  • isDirectory():判断是否是文件夹
  • listFiles():返回一个目录中的文件数组
  • mkdir():创建一个文件夹

3.共有

  • exists():是否存在
  • delete():删除
  • listRoots():返回根目录

例子:获取指定目录下的所有文件和文件夹

public static void get(String path){
        File file = new File(path);
        if (file.exists()) {
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isDirectory()) {
                    System.out.println(f.getPath());
                    get(f.getPath());
                } else {
                    System.out.println(f.getPath());
                }
            }
        }
    }

3、IO流

1.字节流

对文件进行读写操作最底层的,字节流可以对任意格式的文件进行操作

InputStream:读操作的字节流

read():读方法,一次可以从流中读一个字节,返回-1代表读完。

read(byte[] bytes):读方法,将字节读到byte数组中。

read(byte[] bytes, int index, int len):读方法:将字节读到byte数组中,指定起点和长度。

例子:从一个文件中读取数据

// read()方法
public static void readFile(String path){
    FileInputStream in = null;
    try {
        File file = new File(path);
        if (file.exists()) {
            in = new FileInputStream(file);
            int s;
            while ((s = in.read()) != -1) {
                // 将int类型的数字强转成char类型,会自动把数字转成字符
                System.out.println((char)s);
            }
        }
        // 关闭流,建议放在finally中
        in.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// read(byte[] bytes)方法
public static void readFileBytes(String path){
    FileInputStream in = null;
    try {
        File file = new File(path);
        if (file.exists()) {
            in = new FileInputStream(file);
            byte[] b = new byte[in.available()];
            while (in.read(b) != -1) {
                String s = new String(b, "UTF-8");
                System.out.println(s);
            }
        }
        // 关闭流,建议放在finally中
        in.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

OutputStream:写操作的字节流

write():写方法,一次可以向文件中写一个字节

write(byte[] datas):写方法,可以向文件中写入一个字节数组

write(byte[] datas,int startindex,int len):写方法,可以向文件中写入字节数组中指定的字节

例子:向文件中写入数据

public static void write(String path){
    OutputStream out = null;
    try {
        File file = new File(path);
        if (file.exists()) {
            String s = "hello,world";
            byte[] bytes = s.getBytes("UTF-8");
            // 为true表示往文件追加写入,为false表示将覆盖文件内已有的数据
            out = new FileOutputStream(file, true);
            out.write(bytes);
            out.close();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意:流一定要关闭,而且最好放在finally块中,先使用的流后关闭,后使用的流先关闭。

2.字符流

对磁盘文本文件的读写,用字节流可以实现,但不太方便;SUN设计专业的一组流(字符流),对文本格式的文件进行读写操作,相对字节流,要方便一些;为了提供效率,再用上SUN设计的缓冲流。

可以通过字符流读文本格式文件,但不能用来读图片文件,声音文件,视频文件等。

Reader:读操作的字符流

Writer:写操作的字符流

方法与字节流类似

3.字符缓冲流

字符缓冲流只能对字符流进行缓冲 ,字符缓冲流有2个:BufferedReader , BufferedWriter

readLIne():读取一行的数据

newLine():换行

write():写入一行数据

4.其他流

1.标准输入输出流

System.in:获取键盘的数据

System.out:输出到控制台

2.转换流

将字节流转换为字符流(单向)

// 读的转换
InputStream in = new FileInputStream("D:/");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

// 写的转换
OutputStream out = new FileOutputStream("D:/");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));

3.对象流

对象流:将一个对象持久化

序列化:将对象转为流,用来存贮或者网络传输

反序列化:将流中的数据转为对象

:一个类创建的对象要能够被序列化,此类必须实现Serializable接口

public class ObjectOutputStream extends OutputStream
public class ObjectInputStream extends InputStream

4.数据流

数据流:将基本数据类型的数据及字符串持久化;

public class DataInputStream extends FilterInputStream extends InputStream
public class DataOutputStream extends FilterOutoputStream extends OutputStream

4、XML

XML:Extensible Markup Language (可扩展的标签语言),xml是一个纯文本格式的文件,相对文本文件,XML文档的内容一般用标签包裹, XML在项目主要用来存放配制信息或SQL语句

XML文档作用 :存贮数据

XML文档编写规范:

  • 第1行为文档声明,写法固定,一般不需手写,开发工具自动生成
  • xml有且只一个根元素(节点)
  • 标签(元素)需要用一对尖括号包裹起来。标签一般是成对出现的,起始标签与结束标签只差“/"
  • xml区分大小写,一般用小写
  • 元素可以有属性,多个属性需要用空格分开,属性值需要用双引号括起来,属性需要放到起始标签中

XML文档一般3 三种写法

<?xml version="1.0" encoding="UTF-8"?>
<users>
 	<user>
		<name>张三</name>
		<job>C程序员</job>
		<nick>高级程序员</nick>
		<email>zhang@qq.com</email>
	</user>
</users>
<?xml version="1.0" encoding="UTF-8"?>
<users>
	<user name="张一" job="菜鸟" nick="初级程序员" email="zhang@qq.com"  />
	<user name="张二" job="老鸟" nick="高级程序员" email="zhanger@qq.com"/>
</users>
<?xml version="1.0" encoding="UTF-8"?>
<users>
	<user id="1">
		<name>张一</name>
		<job>程序员</job>
		<nick>高级</nick>
		<email>zhang@qq.com</email>
	</user>
</users>

解析XML:在JDK中SUN设计了一组类与接口,用来解析XML文档。SUN设计的解析XML的组件用起来不太方便,所以在实际应用,一般采用第三方解析组件DOM4J ,具体可以网上查询相关资料

默认,没添加任意约束的XML文档的编写是随意的,标签名任意,标签包含的标签设计也是随意的,这样带来的最大缺点:不好解析,不能写一段程序来解析任意结构的XML文件,文档结构混乱的,所以就需要一个结构确定的XML文件给当前XML设计文档结构

XML的约束有2种:DTD和Schema,在这里就不介绍了,有兴趣的可以自己去专研

五、反射

1、反射

在程序运行时,可以根据给定的类动态的获取类的信息

通过反射方式使用此类 SUN设计的反射相关组件放在:java.lang.reflect

探测器对象(Class类型的对象):反射主要就是靠Class进行

获取Class:

// 方法一
User user = new User();
Class<?> c =  user.getClass();
// 方法二
Class<?> clz2 = User.class;
// 方法三,className:类的全路径
Class<?> clz3 =	Class.forName(className); 
// 对基本数据类型的包装类
Class<?> clz4 = Integer.TYPE;
// 获取Class类的父类的Class对象,只能通过这种方式
Class<?> clz4 = String .class.getSuperClass();

2、类加载器(ClassLoader)

类加载器负责在运行时将 Java 类动态的加载到 JVM中,是 JRE的一部分。因此,借助类加载器,JVM 无需了解底层文件或文件系统即可运行 Java 程序。

类不会一次全部加载到内存中,而是在应用程序需要它们时才会进行加载。

类加载器分三种:

  • Application ClassLoader:系统类加载器(应用类加载器),继承扩展类加载器,加载的是一个项目中bin文件夹里的文件,即开发者自己写的类
  • Extension ClassLoader:扩展类加载器,继承引导类加载器,加载的是jdk目录下jre/lib/ext内的文件
  • Bootstrap ClassLoader:引导类加载器,该加载器是内嵌在jvm中一段特殊的用来加载java核心类库的C++代码,引导类加载器不是java原生代码编写的,所以没有实例,为null,加载的是jdk目录下jre/lib中的rt.jar及其他重要文件
// 1、系统类加载器
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
// 2、扩展类加载器
ClassLoader loader2 = loader1.getParent();  
// 3、引导类加载器
ClassLoader loader3 = loader1.getParent();  //null

properties文件

  • 该文件一般用于存放配置
  • 格式为key-value键值对
  • 一行放一个key-value键值对

应用:通过类加载器获取项目资源

ClassLoader loader1 = ClassLoader.getSystemClassLoader();
InputStream in = loader1.getResourceAsStream("db.properties");
//对properties文件,SUN设计了一个类:Properties类,直接解析此文件
Properties prop = new Properties();
prop.load(in);	
//获取文件信息
String user = prop.getProperty("user");
String password = prop.getProperty("password");
System.out.println("user ->" + user);
System.out.println("password -> " + password);

3、获取类信息

1.获取类属性

拥有Field、Constructor和Method三种类型

public static void main(String[] args) throws Exception{

    Class<?> c = Persion.class;

    // 获取类的属性
    Field[] fields = c.getDeclaredFields();
    // 获取该属性所爱的类或接口的名称
    System.out.println(fields[0].getDeclaringClass());
    for (Field f : fields) {
        System.out.println(String.format("%s %s %s;", Modifier.toString(f.getModifiers()), f.getType(), f.getName()));
    }

    // 获取类的构造方法
    Constructor<?>[] constructors = c.getDeclaredConstructors();
    for (Constructor<?> constructor : constructors) {
        System.out.println(constructor);
    }

    // 获取类的成员方法
    Method[] methods = c.getDeclaredMethods();
    for (Method m : methods) {
        System.out.println(m);
    }

}

注:方法中带有Declared的为仅获取本类的类型,去掉Declared的方法为获取本类及其父类的类型

4、反射应用

应用 :创建对象、设置属性、调用方法

public static void main(String[] args) throws Exception{

    Class<?> c = Persion.class;

    // 创建对象
    // 无参构造方法创建
    Persion p1 = (Persion) c.newInstance();
    Constructor<?> constructor = c.getDeclaredConstructor(int.class, String.class, String.class);
    Persion p2 = (Persion) constructor.newInstance(1, "张三", "1333333333");

    // 设置属性,设置上方的p1的name
    Field field = c.getDeclaredField("name");
    // 设置为true,使属性可访问,因为该属性是private的
    field.setAccessible(true);
    field.set(p1, "李四");
    System.out.println(p1);

    // 调用方法,调用p2的show方法
    Method method = c.getDeclaredMethod("show", String.class);
    Object result = method.invoke(p2, "张三");
    System.out.println(result);
}

5、IOC原理

IOC:Inverstion Of Control:控制反转,将程序中对象创建的控制权由用户转交给Spring IOC容器,程序中需要用到哪此对象,直接从容器中取

容器中的对象:会在项目启动时,完成初使化

Spring IOC容器通过反射创建对象

任何一个框架,都有配制文件,框架在运行会读取配制,根据配制文件完成项目必须设制及初使化

所以IOC容器就是根据配制中要初使化的对象,在项目启动时,完成对象的创建

6、AOP原理

AOP:Aspect Oriented Programming :面向切面编程,实现的是对功能的扩展不需要通过修改源码实现,而是在程序运行中动态注入进来

将方法的内的核心业务与非核心业务分离,非核心业务切出去,非核心业务在程序运行时可以通过代理模式动态的植入进来

IOC和AOP为spring的内容,有兴趣的可以搜索相关资料

4、反射应用

应用 :创建对象、设置属性、调用方法

public static void main(String[] args) throws Exception{

    Class<?> c = Persion.class;

    // 创建对象
    // 无参构造方法创建
    Persion p1 = (Persion) c.newInstance();
    Constructor<?> constructor = c.getDeclaredConstructor(int.class, String.class, String.class);
    Persion p2 = (Persion) constructor.newInstance(1, "张三", "1333333333");

    // 设置属性,设置上方的p1的name
    Field field = c.getDeclaredField("name");
    // 设置为true,使属性可访问,因为该属性是private的
    field.setAccessible(true);
    field.set(p1, "李四");
    System.out.println(p1);

    // 调用方法,调用p2的show方法
    Method method = c.getDeclaredMethod("show", String.class);
    Object result = method.invoke(p2, "张三");
    System.out.println(result);
}

5、IOC原理

IOC:Inverstion Of Control:控制反转,将程序中对象创建的控制权由用户转交给Spring IOC容器,程序中需要用到哪此对象,直接从容器中取

容器中的对象:会在项目启动时,完成初使化

Spring IOC容器通过反射创建对象

任何一个框架,都有配制文件,框架在运行会读取配制,根据配制文件完成项目必须设制及初使化

所以IOC容器就是根据配制中要初使化的对象,在项目启动时,完成对象的创建

6、AOP原理

AOP:Aspect Oriented Programming :面向切面编程,实现的是对功能的扩展不需要通过修改源码实现,而是在程序运行中动态注入进来

将方法的内的核心业务与非核心业务分离,非核心业务切出去,非核心业务在程序运行时可以通过代理模式动态的植入进来

IOC和AOP为spring的内容,有兴趣的可以搜索相关资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1 单项选择题 1. 数据结构是一门研究非数值计算的程序设计问题,数据元素的① 、数据信息在计算机的② 以及一组相关的运算等的课程。 ① A.操作对象   B.计算方法  C.逻辑结构  D.数据映象 ② A.存储结构 B.关系 C.运算 D.算法 2. 数据结构DS(Data Struct)可以被形式地定义为DS=(D,R),其D是① 的有限集合,R是D上的② 有限集合。 ① A.算法 B.数据元素 C.数据操作 D.数据对象 ② A.操作 B.映象 C.存储 D.关系 3. 在数据结构,从逻辑上可以把数据结构分成 。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 4. 算法分析的目的是① ,算法分析的两个主要方面是② 。 ① A. 找出数据结构的合理性 B. 研究算法的输入和输出的关系 C. 分析算法的效率以求改进 D. 分析算法的易懂性和文档性 ② A. 空间复杂性和时间复杂性 B. 正确性和简明性 C. 可读性和文档性 D. 数据复杂性和程序复杂性 5. 计算机算法指的是① ,它必具备输入、输出和② 等五个特性。 ① A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 ② A. 可行性、可移植性和可扩充性 B. 可行性、确定性和有穷性 C. 确定性、有穷性和稳定性 D. 易读性、稳定性和安全性 1.2 填空题(将正确的答案填在相应的空) 1. 数据逻辑结构包括 、 、 和 四种类型,树形结构和图形结构合称为 。 2. 在线性结构,第一个结点 前驱结点,其余每个结点有且只有 个前驱结点;最后一个结点 后续结点,其余每个结点有且只有 个后续结点。 3. 在树形结构,树根结点没有 结点,其余每个结点有且只有 个直接前驱结点,叶子结点没有 结点,其余每个结点的直接后续结点可以 。 4. 在图形结构,每个结点的前驱结点数和后续结点数可以 。 5. 线性结构元素之间存在 关系,树形结构元素之间存在 关系,图形结构元素之间存在 关系。 6. 算法的五个重要特性是__ __ , __ __ , ___ _ , __ __ , _ ___。 7. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0;j<n; j++) A[i][j]=0; 8. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0; j<i; j++) A[i][j]=0; 9. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 s=0; for (i=0;i<n;i++) for (j=0;j<n;j++) for (k=0;k<n;k++) s=s+B[i][j][k]; sum=s; 10. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 int i=0,s=0; while (s<n) { i++; s+=i; //s=s+i } 11. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 i=1; while (i<=n) i=i*2;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值