JAVA from entry to proficiency (2) advanced articles

1. Objects and classes

object

Concept : Everything is an object, and an object is the entity in which things exist.

The object consists of two parts: the static part (the part that cannot be modified, this part is called "property"), and the dynamic part (the method that the object has)

An object can be considered as a special case abstracted from a class of things, and the problems that arise in this class of things can be dealt with through this special case

//JAVA语言中使用new操作符调用构造方法创建对象
public Object(){  //构造方法
    System.out.println("创建对象");
}

Access object properties and methods : After using the new operator to create an object, you can use "object.class member" to obtain the properties and behavior of the object.

Object reference : class name object reference name---Example: Book book; reference only stores the memory address of an object, not an object

Object comparison : "=" operator and equals() method

Object destruction: Each object has a life cycle. When the life cycle of the object ends, the memory address allocated to the object will be recycled (Java has a complete garbage collection mechanism, and the garbage collector will recycle useless but memory-consuming resources)

Garbage : The object reference exceeds its scope, and this object will be regarded as garbage; assign the object to null;

Limitations of the garbage collection mechanism: only those objects created by the new operator can be recovered.

JAVA provides the System.gc() method to force the garbage collector to start

kind

Concept: A class is a general term for the same type of things. If a thing in the real world is abstracted into an object, a class is a general term for such objects.

A class is a carrier that encapsulates the attributes and behaviors of an object, that is to say, a class of entities with the same attributes and behaviors is called a class.

In the Java language, the behavior of an object in a class is defined in the form of a method, the properties of an object are defined in the form of member variables, and a class includes the properties and methods of an object.

class and object relationship

The essence of a class is the carrier that encapsulates the attributes and behaviors of an object, and an object is an abstracted instance of a class.

What are the three characteristics of object-oriented?

The object-oriented programming method has three basic characteristics: encapsulation, inheritance, and polymorphism.

  • Encapsulation: refers to encapsulating the properties and methods of an object, and its carrier is a class, which usually hides the implementation details of the object, and then exposes the function of the object through some public methods; (to avoid the impact of external operations on internal data , to improve program maintainability)

  • Inheritance: It is an important means of object-oriented software reuse. When a subclass inherits the parent class, the subclass, as a special parent class, will directly obtain the properties and methods of the parent class;

  • Polymorphism : refers to the fact that subclass objects can be directly assigned to parent class variables, but still exhibit the behavior characteristics of subclasses at runtime, which means that objects of the same type may exhibit multiple behaviors when executing the same method feature.

class constructor

Construction method: In variable assignment, when instantiating an object of this class, the corresponding member variables will also be initialized. If there is no explicit constructor defined in the class, the compiler will automatically create a default constructor with no parameters except in the class A special type of method other than member methods. The construction method is a method with the same name as the class. Object creation is done through the construction method. Whenever a class instantiates an object, the class will automatically call the construction method. Features: The construction method has no return value, and the name of the construction method must be the same as the name of the class. In the construction method, values ​​can be assigned to member variables, so that when an object of this class is instantiated, the corresponding member variables will also be initialized. If in the class If no constructor is explicitly defined, the compiler will automatically create a default constructor with no parameters

//定义无参构造方法
public Lei(){   //public-构造方法修饰符,Lei--构造方法的名称
    //构造方法体
    this("this调用有参构造方法"); //使用this调用有参构造方法
    //在无参构造方法中可以使用this调用有参构造方法,但只可以在无参构造方法的第一句使用this调用
    System.out.println("无参构造方法");
}
//定义有参构造方法
public Lei(String name){
    System.out.println("有参构造方法");
}

Object class

The Object class is the parent class of all classes, and it is the highest class in the Java class layer.
Main methods: clone(), finalize(), equals(), toString()---since all classes are subclasses of the Object class , so any class can rewrite the method
getClass() in the Object class to return the Class instance when the object is executed, and then use this instance to call the getName() method to obtain the name of the class---usage: getClass().getName( )
The toString() method returns an object as a string, and returns a String instance. The
equals() method will return false when using the equals() method in a custom class for comparison, because the equals() method is implemented by default using " == "The operator compares the reference addresses of two objects, instead of comparing the contents of the two objects, you need to override the equals() method in your custom class

public class ObjectClass { //Object类

    public String toString(){  //重写toString()方法
        return "在"+getClass().getName()+"类中重写toString()方法";
    }
    public static void main(String[] args) {
        ObjectClass o = new ObjectClass();
        System.out.println(o.getClass().getName());
        System.out.println("打印本类对象:"+o); //自动调用了toString方法
    }
}

2. Abstract classes and interfaces

abstract class

Generally, the parent class is defined as an abstract class, and this parent class needs to be used for inheritance and polymorphism. Objects cannot be instantiated when an abstract class is set in the Java language. abstract is a keyword defining an abstract class. The method defined by this keyword is called an abstract method. An abstract method has no method body. The method itself has no meaning unless it is overridden. After the abstract class is inherited, it is necessary to implement all the abstract methods in it. To ensure the same method name, parameter list, and same return value type, create a non-abstract/abstract method. All subclasses of the abstract class need to implement the abstract methods in the abstract class. cover. In this way, there will be polymorphic problems again. There are too many redundant codes in the program, and the parent class is also very limited. Maybe a subclass that does not need a certain method has to rewrite the method of the parent class. If you put this method in another class, but Java stipulates that a class cannot inherit multiple classes at the same time, facing this problem, the interface appears...

interface

An interface is an extension of an abstract class, which can be regarded as a pure abstract class, and all methods in the interface have no method body. You can encapsulate the methods that multiple subclasses need to use into an interface, and the class that uses this method implements this interface to use this method

  // 定义接口
  public interface 接口名{
        //接口内的方法,接口内的方法必须被定义为public和abstract形式
   }

Interfaces can implement multiple inheritance: class class name implements interface 1, interface 2, interface 3, ...,

The difference between abstract class and interface

  • A class with an abstract modifier is an abstract class, and an abstract class cannot create an instance object. A class containing an abstract method must be defined as an abstract class, and the methods in an abstract class do not have to be abstract. The abstract method defined in the abstract class must be implemented in the concrete (Concrete) subclass, so there cannot be an abstract constructor or abstract static method. If the subclass does not implement all the abstract methods in the abstract parent class, then the subclass must also be defined as an abstract type.

  • Interface (interface) can be said to be a special case of abstract class, all methods in the interface must be abstract. The method definition in the interface defaults to public abstract type, and the member variable type in the interface defaults to public static final.

interface drawTest{  //定义接口
     void draw();  //定义方法
}
//定义AbstractClassAndInterface类,继承了四边形类,并实现了drawTest接口
class AbstractClassAndInterface  extends Quadrangle implements drawTest{
    //抽象类和接口

    public void draw(){ //因为该类实现了接口,所以要覆盖draw()方法
        System.out.println("draw方法实现");
    }

    public static void main(String[] args) {
        drawTest d = new AbstractClassAndInterface();
        d.draw(); //调用draw方法
    }

}

3. Exception handling

Get exception information

Exception is the variable type that the try code block passes to the catch code block, and e is the variable name

  • getMessage() function: output error properties

  • toString() function: gives the type and nature of the exception

  • printStackTrace() function: point out the type, nature, stack level and location of the exception in the program

Java built-in exception classes

The Java language defines some exception classes in the java.lang standard package.

Subclasses of the standard runtime exception classes are the most common exception classes. Since the java.lang package is loaded into all Java programs by default, most exceptions inherited from the runtime exception class can be used directly.

Java also defines some other exceptions according to various class libraries, and the following table lists Java's unchecked exceptions.

abnormal describe
ArithmeticException This exception is thrown when an abnormal operation condition occurs. For example, an instance of this class is thrown when an integer is "divided by zero".
ArrayIndexOutOfBoundsException Exception thrown when accessing an array with an illegal index. An index is an illegal index if it is negative or greater than or equal to the size of the array.
ArrayStoreException Exception thrown when attempting to store an object of the wrong type into an array of objects.
ClassCastException Thrown when an attempt is made to cast an object to a subclass that is not an instance.
IllegalArgumentException The exception thrown indicates that an illegal or incorrect parameter was passed to the method.
IllegalMonitorStateException Thrown to indicate that a thread has attempted to wait on the object's monitor, or has attempted to notify another thread that is waiting on the object's monitor without specifying a monitor itself.
IllegalStateException Signal generated when a method is called at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
IllegalThreadStateException Exception thrown when the thread is not in the appropriate state required by the requested operation.
IndexOutOfBoundsException Thrown to indicate that a sort index (such as sorting an array, string, or vector) is out of bounds.
NegativeArraySizeException This exception is thrown if the application attempts to create an array with a negative size.
NullPointerException nullThrown when an application attempts to use where an object is expected
NumberFormatException This exception is thrown when an application attempts to convert a string to a numeric type, but the string cannot be converted to the appropriate format.
SecurityException Exception thrown by the security manager to indicate a security violation.
StringIndexOutOfBoundsException This exception is thrown by Stringthe method to indicate that the index is either negative, or exceeds the size of the string.
UnsupportedOperationException This exception is thrown when the requested operation is not supported.

The following table lists the checked exception classes that Java defines in the java.lang package.

abnormal describe
ClassNotFoundException When the application tries to load a class, the corresponding class cannot be found, and this exception is thrown.
CloneNotSupportedException This exception is thrown when the method in the Objectclass is called cloneto clone an object whose class cannot implement Cloneablethe interface .
IllegalAccessException This exception is thrown when access to a class is denied.
InstantiationException This exception is thrown when an attempt is Classmade newInstanceto create an instance of a class using a method in a class, and the specified class object cannot be instantiated because it is an interface or an abstract class.
InterruptedException This exception is thrown when a thread is interrupted by another thread.
NoSuchFieldException The requested variable does not exist
NoSuchMethodException The requested method does not exist

custom exception

Users only need to inherit the Exception class to customize exceptions

Steps to use a custom exception class:

  • Create a custom exception class

  • Throw an exception object through the throw keyword in the method

  • If the exception is handled in the method that currently throws the exception, you can use the try-catch statement block to catch and handle it, otherwise, use the throws keyword to indicate the exception to be thrown to the method caller at the statement in the method

  • Catch and handle the exception in the caller of the exception method

Java exception class structure

Exception classes are defined in each package of the Java class library, all of which are subclasses of the Throwable class. The Throwable class derives two subclasses, Exception and Error classes, and the Error class and its subclasses are used to describe internal errors and resource exhaustion errors that occur in the Java runtime system.

Runtime exception: RuntimeException is an exception that occurs during the running of the program.

Exception usage principles

  • Use a try-catch statement in the current method declaration to catch the exception

  • When a method is overridden, the overriding method must throw the same exception or a subclass of exception

  • If the parent class throws multiple exceptions, the overriding method must throw a subset of those exceptions and cannot throw new exceptions

public class ExceptionP {   //异常处理
    public static void main(String[] args) {
        /*捕获异常:try、catch、finally
                  try存放的是可能存在异常的java语句
                  catch程序块在try之后用来激发被捕获的异常
                  finally是异常处理结构的最后执行部分
         */
        try{
            String str ="lili";
            System.out.println(str+"年龄是:");
            int age = Integer.parseInt("20L");
            System.out.println(age);
        }catch (Exception e){
            e.printStackTrace(); //输出异常性质
            /*
            Exception是try代码块传递给catch代码块的变量类型,e是变量名
            获取异常信息:getMessage()函数:输出错误性质
                        toString()函数:给出异常的类型与性质
                        printStackTrace()函数:指出异常的类型、性质、栈层次及出现在程序中的位置

            本行输出:java.lang.NumberFormatException: For input string: "20L"
	                    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	                    at java.lang.Integer.parseInt(Integer.java:580)
	                    at java.lang.Integer.parseInt(Integer.java:615)
	                    at Basic.ExceptionP.main(Basic.ExceptionP.java:13)
             */
        }
        System.out.println("program over");  //正常输出
        //java的异常处理是结构化的,当try代码块中的语句发生异常时,程序就会跳转到catch代码块中执行,执行完catch代码块中的程序代码后,
        //将继续执行 catch代码块后的其他代码,不会因为一个异常影响整个程序的运行

        /*finally语句块
             完整的异常处理语句一定要包含finally语句,无论程序中有无异常发生,并且无论之前的try-catch是否顺利执行完毕,都会执行finally语句
             四种特殊情况,finally块不会被执行:finally语句块发生了异常
                                           在前面的代码中使用了System.exit()退出程序
                                           程序所在的线程死亡
                                           关闭CPU

         */

    }
}
public class SelfDefinedExc extends Exception{  //自定义异常
    //该类继承Exception
    public SelfDefinedExc(String ErrorMesssage){
        super(ErrorMesssage); //父类构造方法
    }

}

4. Collection class

Collections vs Arrays

  • The length of the array is fixed, and the length of the collection is variable;

  • Arrays are used to access basic data types, and collections are used to access object references

Collection Class Inheritance Relationship

Collection interface

The List interface and the Set interface inherit the Collection interface, and the following methods are common

method Function
add(E e) Add the specified object to this collection
remove(Object o) removes the specified object from this collection
isEmpty() Return boolean to judge whether the current collection is empty
iterator() Returns an iterator over the elements of this Collection, used to traverse the objects in the collection
size() Returns the number of elements in the collection
public class iteratorP {
    public static void main(String[] args) {
        Collection<String> list = new ArrayList<>();  //实例化集合类对象
        list.add("a");
        list.add("b");
        list.add("c");
        //遍历集合都是通过Iterator迭代器实现的
        Iterator<String> it = list.iterator(); //创建迭代器,Collection接口的iterator方法返回此接口中的迭代器
        while(it.hasNext()){ //判断是否有下一个元素
            String str =(String) it.next();  //Iterator的next返回的是Object
            System.out.println(str);
        }
    }
}

List collection

The List collection includes the List interface and all implementation classes of the List interface. The elements in the List collection are allowed to be repeated, and the order of each element is the order in which the objects are inserted. Like an array, users can access elements in a collection by using an index.

List interface: inherits the Collection interface, including all the methods of Collection, and also includes the following methods

  • get(int index) : get the element at the specified index position

  • set(int index, Object obj): modify the object at the specified index position in the collection to the specified object

Implementation class: ArrayList and LinkedList

ArrayList class: implements a mutable array, allows to save all elements, including null, and can perform fast random access to the collection according to the index position; the disadvantage is that the speed of inserting or deleting objects to the specified index position is slow.

LinkedList class : uses a linked list structure to store objects. The advantage is that it is convenient to insert and delete objects into the collection, and the efficiency of random access to objects is low.

实例化:
List<E> list = new ArrayList<>();
List<E> list = new LinkedList<>();
//E是数据类型
public class ListC {  //List集合
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();  //创建集合对象
        list.add("a");
        list.add("b");
        list.add("c");
        int i = (int)(Math.random()*(list.size()-1));//随机获取索引
        System.out.println("随机获取数组中的元素:"+list.get(i));

        list.remove(2);  //将指定位置的元素从集合中移除
        System.out.println("数组中剩余元素:");
        for (int j =0;j<list.size();j++){
            System.out.println(list.get(j));
        }
    }
}

Set collection

The objects in the Set collection are not sorted in a specific way, but the objects are simply added to the collection, but the Set collection cannot contain duplicate objects.

Inherited the Collection interface, including all the methods of Collection

Implementation class

HashSet class: implements the Set interface, supported by a hash table (actually a HashMap instance), does not guarantee the iteration order of the Set, especially it does not guarantee that the order is constant, and allows the use of null elements.

TreeSet class: Not only implements the Set interface, but also implements the java.util.SortedSet interface. The Set collection implemented by the TreeSet class is sorted incrementally according to the natural order when traversing the collection, and can also be sorted incrementally according to the specified comparator.

Added methods of TreeSet class

method Function
first() Returns the current first element in this Set
last() Returns the last element currently in this Set
comparator() Returns a comparator that sorts the elements in this Set. Returns null if natural order
headSet(E toElement) Returns a new Set collection, the new collection contains all objects before toElement (not included)
subSet(E fromElement,E toElement) Returns a new Set collection containing all objects between the fromElement (inclusive) object and the toElement (exclusive) object
tailSet(E fromElement) Returns a new collection containing all objects after the object fromElement(contains)
public class SetC implements Comparable<Object>{  //创建类实现Comparable接口
    //存入TreeSet类实现的Set集合必须实现Comparable接口,该接口中的compareTo(object o)方法比较此对象与指定对象的顺序
    String name;
    long id;
    public SetC(String name,long id){  //构造方法
        this.id = id;
        this.name = name;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getId(){
        return this.id;
    }
    public String getName(){
        return this.name;
    }

    @Override
    public int compareTo(Object o) {
        SetC set = (SetC) o;
        int result = id>set.id?1:(id==set.id?0:-1);
        return result;
    }

    public static void main(String[] args) {
        SetC s1 = new SetC("李同学",01011);
        SetC s2 = new SetC("陈同学",01021);
        SetC s3 = new SetC("王同学",01051);
        SetC s4 = new SetC("沈同学",01012);
        TreeSet<SetC> tree = new TreeSet<>();
        tree.add(s1);
        tree.add(s2);
        tree.add(s3);
        tree.add(s4);
        Iterator<SetC> it = tree.iterator();//Set集合中所有对象的迭代器
        System.out.println("遍历集合:");
        while(it.hasNext()){
            SetC s = (SetC) it.next();
            System.out.println(s.getId()+" "+s.getName());
        }
        it = tree.headSet(s2).iterator();  //截取排在s2之前的对象
        System.out.println("截取前面部分的集合:");
        while(it.hasNext()){
            SetC s = (SetC) it.next();
            System.out.println(s.getId()+" "+s.getName());
        }
        it = tree.subSet(s2,s3).iterator();  //截取在s2和s3之间的对象
        System.out.println("截取中间的集合:");
        while(it.hasNext()){
            SetC s = (SetC) it.next();
            System.out.println(s.getId()+""+s.getName());
        }
    }
}

Map collection

The Map collection provides a key-to-value mapping. Maps cannot contain the same key, and each key can only map to one value. The key also determines the storage location of the storage object in the map, but not by the key object itself, but through a "hashing technique" to generate an integer value of a hash code, which is usually used as An offset corresponding to the starting position of the memory area allocated to the map, thereby determining the storage position of the storage object in the map.

Common methods:

method Function
put(K key,V value) Add the mapping relationship between the specified key and value to the collection
containsKey(Object key) Returns true if this map contains a mapping for the specified key
containsValue(Object value) Returns true if this map maps one or more keys to the specified value
get(Object key) If the specified key object exists, return the value corresponding to the object, otherwise return null
keySet() Returns the Set collection formed by all key objects in the collection
values() 返回该集合中所有值对象形成的Collection集合

实现类

HashMap类:基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。HashMap通过哈希表对其内部的映射关系进行快速查找。此类不保证映射的顺序,特别是不保证该顺序恒久不变。

TreeMap类:不仅实现了Map接口,还实现了java.util.SortedMap接口,因此集合中的映射关系存在一定的顺序。但在添加、删除和定位映射关系时,TreeMap比HashMap类性能稍差。由于TreeMap类实现的Map集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null。

public class MapC {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>(); //创建Map实例
        map.put("01","李同学");
        map.put("02","位同学");
        map.put("03","张同学");
        Set<String> set = map.keySet(); //构建Map集合中所有key对象的集合
        Iterator<String> it = set.iterator(); //创建集合迭代器
        System.out.println("key集合中的元素:");
        while(it.hasNext()){
            System.out.println(it.next());
        }
        Collection<String> coll = map.values(); //构建Map集合中所有的values值集合
        it = coll.iterator();
        System.out.println("values值集合中的元素:");
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}

五、I/O输入输出

java.io包中存放许多负责各种方式的输入/输出的类,其中,输入流类是抽象类InputStream(字节输入流)或抽象类Render(字符输入流)的子类。所有的输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。

输入流和输出流的类层次图

 

输入流

InputStream(字节输入流),是所有字节输入流的父类。该类中的所有方法遇到错误都会引发IOException异常

常用方法

  • read()方法--从输入流中读取数据的下一个字节。返回0~255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节则返回-1

  • read(byte[] b)---从输入流中读入一定长度的字节,并以整数的形式返回字节数

  • mark(int readlimit)---在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数

  • reset()方法---将输入指针返回到当前所做的标记处

  • skip(long n)---跳过输入流上的n个字节并返回实际跳过的字节数

  • markSupported()---如果当前流支持mark()/reset()操作就返回true

  • close()--关闭此输入流并释放与该留关联的所有系统资源

并不是所有的InputStream类的子类都支持InputStream中定义的所有方法

Render类是字符输入流的抽象类,所有字符输入流的实现都是它的子类

输出流

OutputStream类是字节输出流的抽象类,此抽象类表示输出字节流的所有类的超类。

OutputStream类中的所有方法均返回void,在遇到错误时触发IOException异常。

常用方法

  • write(int b)---将指定的字节写入此输出流

  • write(byte[] b)--将b个字节从指定的byte数组写入此输出流

  • write(byte[],int off,int len)--将指定byte数组中从偏移量off开始的len个字节写入此输出流

  • flush()--彻底完成输出并清空缓存区

  • close()--关闭输出流

Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类

File类

File类是java.io包中唯一代表哦磁盘文件本身的对象。File类定义了一些方法来操作文件,实现创建、删除、重命名文件等操作。

文件的创建和删除

3种构造方法

  • File(String pathname)---通过将给定路径名字符串转换为抽象路径来创建一个新的File实例

New File(String pathname)
File file = new File("d:/1.txt") //指定路径名称,包含文件名
  • File(String parent,String child)---根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象

new File(String parent,String child)
    
//parent:父路径字符串 D:/或D:/doc
    
//child:子路径字符串 letter.txt
  • File(File f,String child)---根据parent抽象路径名和child路径名字符串创建一个新的File实例

    new File(File f,String child)
    //f:父路径对象  D:/doc/
    //child:子路径字符串  letter.txt

获取文件信息

方法描述
public String getName() ---返回由此抽象路径名表示的文件或目录的名称。
public String getParent()---返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null
public File getParentFile() ---返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null
public String getPath() -----将此抽象路径名转换为一个路径名字符串。
public boolean isAbsolute() ---测试此抽象路径名是否为绝对路径名。
public String getAbsolutePath() ----返回抽象路径名的绝对路径名字符串。
public boolean canRead()--- 测试应用程序是否可以读取此抽象路径名表示的文件。
public boolean canWrite()--- 测试应用程序是否可以修改此抽象路径名表示的文件。
public boolean exists() ----测试此抽象路径名表示的文件或目录是否存在。
public boolean isDirectory()---- 测试此抽象路径名表示的文件是否是一个目录。
public boolean isFile() ----测试此抽象路径名表示的文件是否是一个标准文件。
public long lastModified() ---返回此抽象路径名表示的文件最后一次被修改的时间。
public long length() ---返回由此抽象路径名表示的文件的长度。
public boolean createNewFile() throws IOException --当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件。
public boolean delete() ----删除此抽象路径名表示的文件或目录。
public void deleteOnExit() ----在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
public String[] list() ---返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。
public String[] list(FilenameFilter filter) 返---回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的。
public File[] listFiles() -返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。
public File[] listFiles(FileFilter filter) --返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。
public boolean mkdir() ---创建此抽象路径名指定的目录。
public boolean mkdirs() ---创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
public boolean renameTo(File dest) ---重新命名此抽象路径名表示的文件。
public boolean setLastModified(long time) ---设置由此抽象路径名所指定的文件或目录的最后一次修改时间。
public boolean setReadOnly() ---标记此抽象路径名指定的文件或目录,以便只可对其进行读操作。
public static File createTempFile(String prefix, String suffix, File directory) throws IOException--- 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
public static File createTempFile(String prefix, String suffix) throws IOException --在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
public int compareTo(File pathname) ---按字母顺序比较两个抽象路径名。
public int compareTo(Object o) ---按字母顺序比较抽象路径名与给定对象。
public boolean equals(Object obj) ----测试此抽象路径名与给定对象是否相等。
public String toString() ----返回此抽象路径名的路径名字符串。
public boolean isHidden() --- 判断文件是否是隐藏文件

文件输入/输出流

程序运行期间,大部分数据都在内存中进行操作,当程序结束或关闭时,这些数据将消失,如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。

FileInputStream和FileOutputStream类

FileInputStream和FileOutputStream类都是用来操作磁盘文件,分别是InputStream和OutputStream类的子类,提供文件的读取和写入能力。

构造方法

  • FileInputStream(String name)---使用给定的文件名创建一个FileInputStream对象

  • FileInputStream(File file) --- 使用File对象创建FileInputStream对象

  • FileOutputStream(String name)---使用给定的文件名创建一个FileOutputStream对象

  • FileOutputStream(File file) --- 使用File对象创建FileOutputStream对象

FileReader类和FileWriter类

使用FileInputStream和FileOutputStream类读取和写入内容只能对字节或字节数组,由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象。FileReader类和FileWriter类可避免这种现象

FileReader流顺序的读取文件,只要不关闭流,调用read()方法就顺序的读取源中其余内容,直到源的末尾或流关闭。

带缓存的输入/输出流

BufferedInputStream 与 BufferedOutputStream类

构造函数

  • BufferedInputStream(InputStream in)---创建一个带有32字节的缓存流

  • BufferedInputStream(InputStream in,int size)---按指定的大小来创建缓存区

  • BufferedOutputStream(OutputStream in)---创建一个带有32字节的缓存流

  • BufferedOutputStream(OutputStream in,int size)---按指定的大小来创建缓存区

BufferedOutputStream输出信息和用OutputStream输出信息完全相同,但BufferedOutputStream类有一个flush()方法用来将缓存区的数据强制输出完。

注:flush()方法就是用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新。flush方法只对缓存区的OutputStream类的子类有效。当调用close()方法时,系统在关闭流之前,也会将缓存区中信息刷新到磁盘文件中。

BufferedReader与 BufferedWriter类

BufferedReader类常用方法

  • read() -- 读取单个字符

  • readline() --- 读取一个文本行,并将其返回字符串。若无数据可读则返回null

BufferedWriter类中的方法否返回void,常用方法

  • write(String s,int off,int len) --- 写入字符串的某一部分

  • flush() --- 刷新该流的缓存

  • newLine() -- 写入一个行分隔符

使用BufferedWriter类的write方法时,数据并没有立即被写入到输出流,而是首先进入缓存区中,如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法。

数据输入/输出流

DataInputStream类与DataOutputStream类允许应用程序以与机器无关的方法从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。

构造方法

  • DataInputStream(InputStream in) --使用指定的基础InputStream创建一个DataInputStream

  • DataOutputStream(OutputStream out) -- 创建一个新的数据输出流,将数据写入指定基础输出流

DataOutputStream类写入字符串的方法

  • writeBytes(String s) -- Java字符是Unicode编码,是双字节的,将字符串中的每一个字符的低字节内容写入目标设备中

  • writeChars(String s) --- 将字符串中的每一个字符的两个字节的内容都写到目标设备中

  • writeUTF(String s) --- 将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码

只有readUTF()方法返回字符串:因为只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确读回写入字符串

ZIP压缩输入/输出流

ZipEntry、ZipInputStream、ZipOutputStream(java.util.zip) 3个类实现ZIP数据压缩方式

压缩文件

ZipOutputStream类对象,可将文件压缩为.zip文件

构造方法:ZipOutputStream(OutputStream out)

常用方法:

  • putNextEntry(ZipEntry e) --开始写一个新的ZipEntry,并将流内的位置移至此entry所指数据的开头

  • write(byte[] b,int off,int len) -- 将字节数组写入当前ZIP条目数据

  • finish()---完成写入ZIP输出流的内容,无需关闭它所配合的OutputStream

  • setComment(String comment) -- 可设置此ZIP文件的注释文字

package IOStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class MyZip { //ZipOutputStream类对象实现文件夹压缩
    private void zip(String zipFileName, File inputFile) throws Exception{
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
        zip(out,inputFile,"");
        System.out.println("压缩中...");
        out.close();
    }
    private void zip(ZipOutputStream out,File f,String base) throws Exception{  //方法重载
        if(f.isDirectory()){ //判断抽象路径名表示的文件是否是一个目录
            File[] fl = f.listFiles(); //获取路径数组
            out.putNextEntry(new ZipEntry(base+"/"));  //写入此目录的entry
            base = base.length()==0?"":base+"/"; //判断参数是否为空
            for(int i=0;i<fl.length;i++){  //循环遍历数组中的文件
                zip(out,fl[i],base+fl[i]);
            }
        }else{
            out.putNextEntry(new ZipEntry(base));  //创建新的进入点
            FileInputStream in = new FileInputStream(f);
            int b; //定义int型变量
            System.out.println(base);
            while((b=in.read())!=-1){
                out.write(b);  //如果没有到达流的尾部,将字节写入当前ZIP条目
            }
            in.close();
        }
    }
    public static void main(String[] args) {
        MyZip book = new MyZip();
        try{
            //调用方法,参数为压缩后的文件和要压缩的文件
            book.zip("hello.zip",new File("hello"));
            System.out.println("压缩完成");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

解压缩ZIP文件

ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)

ZipInputStream构造方法:ZipInputStream(InputStream in)

常用方法:

  • read(byte[] b,int off,int len) -- 读取目标b数组内off偏移量的位置,长度是len字节

  • available() -- 判断是否已读完目前enrty所指定的数据,已读完返回0,否则返回1

  • closeEntry() -- 关闭当前ZIP条目并定位流以读取下一个条目

  • skip(long n) -- 跳过当前ZIP条目中指定的字节数

  • getNextEntry() -- 读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头

  • createZipEntry(String name) -- 以指定的name参数新建一个ZipEntry对象

注:使用ZipInputStream类来解压文件,必须先使用ZipInputStream类的getNextEntry方法来获取其内的第一个ZipEntry

import java.io.File;
import java.io.FileInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class InZIP {  //解压文件
    public static void main(String[] args) {
        ZipInputStream zin;
        try{
            //实例化对象,指明要解压的文件
            zin = new ZipInputStream(new FileInputStream("hello.zip"));
            //使用ZipInputStream类来解压文件,必须先使用ZipInputStream类的getNextEntry方法来获取其内的第一个ZipEntry
            ZipEntry entry = zin.getNextEntry(); //获取下一个 ZipEntry
            while(((entry = zin.getNextEntry())!=null)&&!entry.isDirectory()){
                //如果entry不为空并且不在同一目录下
                File file = new File("G:\\Project\\JAVA\\"+entry.getName()); //获取文件目录
                System.out.println(file);
                if(!file.exists()){ //如果文件不存在
                    file.mkdirs();//创建文件所在文件夹
                    file.createNewFile(); //创建文件
                }
                zin.closeEntry();
                System.out.println(entry.getName()+"解压成功");
            }
            zin.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

六、反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

获取class类对象的三种方式

  • class java.lang.String-----对象名.getClass()

  • class java.lang.String-----类名.class

  • class java.lang.String-----Class.forName(...)

Class类的常用方法

  • getName() 一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

  • newInstance() Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。

  • getClassLoader() 返回该类的类加载器。

  • getComponentType() --- 返回表示数组组件类型的 Class。

  • getSuperclass() --- 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。

  • isArray() --- 判定此 Class 对象是否表示一个数组类

通过反射可访问的主要描述信息

组成部分 访问方法 返回值类型 说明
包路径 getPackage() Package对象 获得该类的存放路径
类名称 getName() String对象 获得该类的名称
继承类 getSuperclass() Class对象 获得该类继承的类
实现接口 getInterfaces() Class型数组 获得该类实现的所有接口
构造方法 getConstructors() Constructor型数组 获得所有权限为public的构造方法
getConstructor(Class<?>...parameterTypes) Constructor对象 获得权限为public的指定构造方法
getDeclaredConstructors() Constructor型数组 获得所有构造方法,按声明顺序返回
getDeclaredConstructor(Class<?>...parameterTypes) Constructor对象 获得指定构造方法
方法 getMethods() Method型数组 获得所有权限为public的方法
getMethod(String name,Class<?>...parameterTypes) Method对象 获得权限为public的指定方法
getDeclaredMethods() Method型数组 获得所有方法,按声明顺序返回
getDeclaredMethods(String name,Class<?>...parameterTypes) Method对象 获得指定方法
成员变量 getFileds() Filed型数组 获得所有权限为public的成员变量
getFiled(String name) Filed对象 获得权限为public的指定成员变量
getDeclaredFileds() Filed型数组 获得所有成员变量,按声明顺序返回
getDeclaredFiled(String name) Filed对象 获得指定成员变量
内部类 getClasses() Class型数组 获得所有权限为public的内部类
getDeclaredClasses() Class型数组 获得所有内部类
内部类的声明类 getDeclaringClass() Class对象 如果该类为内部类,则返回它的成员类,否则返回null

注:在通过方法getFileds()和getMethods()依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法;而通过方法getDeclaredFileds()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。

访问构造函数

  • getConstructors()

  • getConstructor(Class<?>...parameterTypes)

  • getDeclaredConstructors()

  • getDeclaredConstructor(Class<?>...parameterTypes)

如果是访问指定的构造函数,需要根据该构造函数的入口参数的类型来访问。例如,访问一个入口参数类型依次为String和int型的构造函数:

objectClass.getDeclaredConstructor(String.class,int.class);
objectClass.getDeclaredConstructor(new Class[]{String.classs,int.class});

Constructor类的常用方法

  • isVarArgs() --- 查看该构造函数是否允许带有可变数量的参数,如果允许则返回true,否则返回false

  • getParameterTypes() -- 按照声明顺序以Class数组的形式获得该构造方法的各个参数的类型

  • getExceptionTypes() -- 以Class数组的形式获得该构造方法可能抛出的异常类型

  • newInstance(Object...initargs) -- 通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法

  • setAccessible(boolean flag) -- 如果该构造方法的权限为private,默认不允许通过反射利用newInstance(Object...initargs)方法创建对象。如果先执行该方法,并将入口参数设为true,则允许创建。

  • getModifiers() -- 获得可以解析出该构造方法所采用修饰符的整数

通过java.lang.reflect.Modifier类可以解析出getModifiers()方法的返回值所表示的修饰符信息

Modifier类的常用解析方法

  • isPublic(int mod) --- 查看是否被public修饰符修饰,返回true/false

  • isProtected(int mod) -- 查看是否被protected修饰符修饰,返回true/false

  • isPrivate(int mod) --- 查看是否被private修饰符修饰,返回true/false

  • isStatic(int mod) -- 查看是否被static修饰符修饰,返回true/false

  • isFinal(int mod) -- 查看是否被final修饰符修饰,返回true/false

  • toString(int mod) -- 以字符串的形式返回该修饰符

访问成员变量

  • getFileds()

  • getFiled(String name)

  • getDeclaredFileds()

  • getDeclaredFiled(String name)

返回Field类型的对象或者数组

Filed类常用方法

  • getName() --- 获得该成员变量的名称

  • getType() --- 获得表示该成员变量类型的Class对象

  • get(Object obj) --- 获得指定对象obj中成员变量的值,返回值为Object型

  • set(Object obj,Object value) -- 将指定对象obj中成员变量的值设置为value

  • getInt(Object obj) -- 获得指定对象obj中类型为int的成员变量的值

  • setInt(Object obj,int i) -- 将指定对象obj中类型为int的成员变量的值设为i

  • getFloat(Object obj) -- 获得指定对象obj中类型为float的成员变量的值

  • setFloat(Object obj,float f) -- 将指定对象obj中类型为float的成员变量的值设为f

  • getBoolean(Object obj) -- 获得指定对象obj中类型为boolean的成员变量的值

  • setBoolean(Object obj,boolean b) -- 将指定对象obj中类型为boolean的成员变量的值设为b

  • setAccessible(boolean flag) 此方法可以设置是否忽略权限限制直接访问private等私有权限的成员变量

  • getModifiers() -- 获得可以解析出该成员变量所采用修饰符的整数

访问方法

  • getMethods()

  • getMethod(String name,Class<?>...parameterTypes)

  • getDeclaredMethods()

  • getDeclaredMethods(String name,Class<?>...parameterTypes)

返回Method类型的对象或数组

Method类的常用方法

  • getName() --- 获得该方法的名称

  • getParameterTypes() -- 按照声明顺序以Class数组的形式获得该方法的各个参数的类型

  • getReturnType() ---以class对象的形式获得该方法的返回值的类型

  • getExceptionTypes() -- 以Class数组的形式获得该方法可能抛出的异常类型

  • invoke(Object obj,Object...args) --利用指定参数args执行指定对象obj中的方法,返回值为Object类型

  • isVarArgs() --- 查看该函数是否允许带有可变数量的参数,如果允许则返回true,否则返回false

  • getModifiers() -- 获得可以解析出该方法所采用修饰符的整数

Annotation

参考:Java反射:使用Annotation功能_pan_junbiao的博客-CSDN博客

定义Annotation类型,@interface关键字(继承了Java.lang.annotation.Annotation接口)

//定义一个Annotation类型
public @interface NoMemberAnnotation{
}
//这样未包含任何成员的Annotation类型称为marker annotation 
//可以定义包含成员变量的类型有String、Class、primitive、enumberated和annotation以及所列类型的数组,如果所定义的Annotation类型中只包含一个成员,通常将成员名称命名为value
public @interface DefaultValueAnnotation{
    //可以为成员设置默认值
    String describe() default "<默认值>";
    Class type() default void.class;
}

在定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Target。

枚举类ElementType中的枚举常量

 通过Annotation类型@Retention可以设置Annotation类型的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention。如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。

枚举类RetentionPolicy中的枚举常量

 访问Annotation信息 如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。

类Constructor、Field和Method均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法,其中方法isAnnotationPresent(Class<? extends Annotation> annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(Class<T> annotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组。

在类Constructor和Method中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。

七、枚举类型和泛型

枚举

继承于java.lang.Enum类

使用枚举类型定义常量方式:

//enum为定义枚举类型关键字
public enum Constants{
     Constants_A,
     Constants_B,
     Constants_C
}
//程序中调用枚举类型常量的方法:Constants.Constants_A
//枚举类型也可以在类的内部以内部类的形式定义
public class A{
    enum B{
        Constants_A,
        Constants_B,
    }
}

枚举类型常用方法

方法名 含义 使用方法
values() 可以将枚举类型成员以数组的形式返回 枚举类型名称.values()
valueOf() 实现将普通字符串转换为枚举实例 枚举类型名称.valueOf("abc")
compareTo() 用于比较两个枚举对象在定义时的顺序 枚举对象.compareTo(枚举对象)
ordinal() 用于得到枚举成员的位置索引 枚举对象.ordinal()

枚举类型声明提供了一种用户友好的变量定义方法,枚举了某种数据类型所有可能出现的值。

特点

  • 类型安全

  • 紧凑有效的数据定义

  • 可以和程序其他部分完美交互

  • 运行效率高

泛型

在泛型之前,Java提供了对Object的引用”任意化“操作,这种任意化操作就是对Object引用进行”向下转型“及”向上转型“操作,但某些强制类型转换的错误也许不会被编译器捕捉,而在运行后出现异常,可见强制类型转换存在安全隐患,所以提供泛型机制解决此问题。

语法:类名<T> T代表一个类型的名称,容器元素使用E表达

使用泛型定义的类在声明该类对象时可以根据不同的需求指定<T>真正的类型,而在使用类中的方法传递或返回数据类型时将不再需要进行类型转换操作。

泛型的用法

  • 定义泛型类时声明多个类型

//1
MutiOverClass<T1,T2>
//2
MutiOverClass:泛型类名称
    
MutiOverClass<Boolean,Float> = new MutiOverClass<Boolean,Float>();
  • 定义泛型类时声明数组类型

public class OverClass<T> {  //定义泛型类
    private T[] array; //定义泛型数组
    public void SetT(T[] array){
        this.array = array;
    }
    public T[] getT(){
        return array;
    }
    public static void main(String[] args) {
        OverClass<String> a = new OverClass<String>();//泛型实例,字符串型数组
        String[] array = {"成员1","成员2","成员3"};
        a.SetT(array);
        for(int i =0;i<a.getT().length;i++){
            System.out.println(a.getT()[i]);  //返回数组中的值
        }
    }
}
  • 集合类声明容器的元素

可以使用K和V两个字符代表容器中的键值与键值对应的具体值

import java.util.HashMap;
import java.util.Map;
public class MultiOverClass<K,V>{  //定义泛型集合
    public Map<K,V> m = new HashMap<K,V>();   //定义一个HashMap实例
    public void put(K k,V v){
        m.put(k,v); //将对应的键值对存入集合对象中
    }
    public V get(K k){
        return m.get(k);
    }
    public static void main(String[] args) {
        MultiOverClass<Integer,String> mu =new MultiOverClass<Integer,String>();
        for(int i=0;i<5;i++){
            mu.put(i,"我是集合成员"+i);  //循环存入键值对给集合
        }
        for(int i=0;i<mu.m.size();i++){
            System.out.println(mu.get(i));  //获取集合中的值
        }
    }
}

被泛型化的集合类--可在主方法中直接使用,不用定义泛型类

  • ArrayList ----泛型定义ArrayList<E>

  • HashMap----泛型定义HashMap<K,V>

  • HashSet----泛型定义HashSet<E>

  • Vector ---- 泛型定义Vector<E>

泛型的高级用法

  • 限制泛型可用类型

class  类名称<T extends anyClass>   //anyClass表示某个接口或类
    
使用泛型限制后,泛型类的类型必须实现或继承了anyClass这个接口或类,无论anyClass是接口还是类,在进行泛型限制时都必须使用extends关键字
public class LimitClass<T extends List> {
    public static void main(String[] args) {
        //实例化已经实现List接口的类
        LimitClass<ArrayList> l1 = new LimitClass<ArrayList>();
        LimitClass<LinkedList> l2 = new LimitClass<LinkedList>();
//        LimitClass<HashMap> l3 = new LimitClass<HashMap>(); //报错,因为HashMap没有实现List接口
    }
}

当没有使用extends关键字限制泛型类类型时,默认Object类下的所有子类都可以实例化泛型类对象。

  • 使用类型通配符

类型通配符的主要作用是在创建一个泛型类对象时限制这个泛型类的类型实现或继承某个接口或类的子类。

//语法
泛型类名称<? extends List> a =null; 
//<? extends List> 表示类型未知,当需要使用该泛型对象时,可以单独实例化
public class CommonClass<T> { //类型通配符泛型
    //将该泛型实例放在方法的参数中
    public void doSomething(CommonClass<? extends List> a){
    }
    public static void main(String[] args) {
        CommonClass<? extends List> a =null;
        a = new CommonClass<ArrayList>();
        a = new CommonClass<LinkedList>();
        //示例
        List<String> l1 = new ArrayList<String>(); //实例化一个ArrayList 对象
        l1.add("成员"); //在集合中添加内容
        List<?> l2 =l1; //使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取和删除
        List<?> l3 = new LinkedList<Integer>();
        System.out.println(l2.get(0));  //获取集合中的第一个值
        l1.set(0,"成员改变");
//        l2.set(0,"成员改变");  //报错
    }
}

泛型类的限制除了可以向下限制之外,还可以进行向上限制,只需要在定义时使用super关键字即可。

A<? super List> a =null; 这样定义后对象a只接受List接口或上层父类类型,如a=new A<Object>();

  • 继承泛型类与实现泛型接口

    定义为泛型的类也可以被继承与实现

    public class ExtendClass<T1>{
         
    }
    class SubClass<T1,T2,T3> extends ExtendClass<T1>{
        
    }
    //定义的泛型接口也可以被实现
    interface i<T1>{
        
    }
    class SubClass2<T1,T2,T3> implements i<T1>{
        
    }

总结

  • 泛型的类型参数只能是类类型(Integer,Long,Short,Boolean,Byte,Character,Double,Float),不可以是简单类型,如A<int>这种泛型定义就是错误的

  • 泛型的类型个数可以是多个

  • 可以使用extends关键字限制泛型的类型

  • 可以使用通配符限制泛型的类型

八、多线程

Windows操作系统是多任务操作系统,它以进程为单位。一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序。系统可以分配给每个进程一段有限的使用CPU的时间,CPU在这段时间中执行某个进程,然后下一个时间片又跳转至另一个进程中去执行。由于CPU转换较快,所以使得每个进程好像是同时执行一样。

一个线程则是进程中的执行流程,一个进程可以同时包括多个线程,每个线程也可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。在单线程中,程序代码按照调用顺序依次往下执行,如果需要一个进程同时完成多段代码的操作,就需要多线程。

多线程的两种实现方式

继承java.lang.Thread类

启动一个新线程需要建立Thread实例

构造方法

  • public Thread(String threadName) --- 创建一个名称为threadName的线程对象

  • public Thread()

实现java.lang.Runnable接口

如果需要继承其他类(非Thread类),而且还要使当前类实现多线程,那么可以通过Runnable接口来实现。

//语法
public class Thread extends Object implements Runnable

实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联。Thread类中有以下构造方法

  • public Thread(Runnable r)

  • puble Thread(Runnable r,Sting name)

使用Runnable接口启动新的线程的步骤:

  • 建立Runnable对象

  • 使用参数为Runnable对象的构造函数创建Thread实例

  • 调用start()方法启动线程

线程的生命周期

  • 出生状态:线程被创建时处于的状态,在用户使用该线程实例调用start()方法之前都处于出生状态

  • 就绪状态:当用户调用start()方法后,线程处于就绪状态(可执行状态)

  • 运行状态:当线程得到系统资源后就进入运行状态

  • 等待状态:当处于运行状态下的线程调用Thread类中的wait()方法时,该线程便进入等待状态,进入等待状态的线程必须调用Thread类中的notify()方法才能被唤醒,而notifyAll()方法是将所有处于等待状态下的线程唤醒。

  • 休眠状态:当线程调用Thread类中的sleep()方法时,则会进入休眠状态

  • 阻塞状态:如果一个线程在运行状态下发出输入/输出请求,该线程将进入阻塞状态,在其等待输入/输出结束时线程进入就绪状态,对于阻塞的线程来说,即使系统资源空闲,线程依然不能回到运行状态。

  • 死亡状态:当线程的run()方法执行完毕时,线程进入死亡状态。

线程处于就绪状态方法

  • 调用sleep()方法

  • 调用wait()方法

  • 等待输入/输出完成

当线程处于就绪状态后,再次进入运行状态:

  • 线程调用notify()方法

  • 线程调用notifyAll()方法

  • 线程调用interrupt()方法

  • 线程的休眠时间结束

  • 输入/输出结束

操作线程的方法

  • 线程的休眠:sleep()方法控制线程的休眠,需要一个参数指定该线程休眠的时间,时间以毫秒为单位

  • 线程的加入:join()方法实现某个线程加入到另外一个线程,另一个线程会等待该线程执行完毕后再继续执行

  • 线程的中断:在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止(stop()方法已废弃)

  • 线程的礼让:yield()方法只是给当前处于运行状态的线程一个提醒,告知它可以将资源礼让给其他线程,但仅仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。yield方法使具有同样优先级的线程有进入可执行状态的机会,当当前线程放弃执行权时会再度回到就绪状态。对于支持多任务的操作系统来说,不需要调用yield方法,因为操作系统会为线程自动分配CPU时间片来执行。

线程的优先级

Thread类中包含的成员变量代表了线程的某些优先级,每个线程的优先级都在Thread.MIN_PRIORATY(1)~Thread.MAX_PRIORATY(10)只见那,默认情况下都是Thread.NORM_PRIORITY(5)。每个新产生的线程都继承了父线程的优先级。

线程的优先级可以使用setPriority()方法调整,如果设置的优先级不在1~10之内,将产生IllegleArgumentException异常。

线程同步

在编写多线程程序时,应该考虑线程安全问题。实质上线程安全问题来源于两个线程同时存取单一对象的数据

线程同步机制:基本上所有解决多线程资源冲突问题的方法都是采用给定时间只允许一个线程访问共享资源,这时就需要给共享资源上一道锁。

java提供同步机制使用synchronized关键字,可以有效防止冲突。

同步块方法:

syncronized(Object){
     //共享资源
}

通常将共享资源放置在syncronized定义的区域内,这样当其他线程也获取到这个所时,必须等待锁被释放时才能进入该区域。Object为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为0和1.一个线程运行到同步块时首先检查该对象的标志位,如果为0状态,表明此同步块中存在其他线程在运行。这时该线程处于就绪状态,直到处于同步块中的线程执行完同步块中的代码为止。这时该对象的标志位被设置为1,该进程才能执行同步块中的代码,并将Object对象的标志位设置为0,防止其他线程执行同步块中的代码。

同步方法:

syncronized void f(){ //方法前面修饰syncronized关键字的方法
}

当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步的方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为syncronized,否则就会出错。

九、网路通信

Internet网络依靠TCP/IP协议,在全球范围内实现不同的硬件结构、不同的操作系统、不同网络系统的互连。TCP/IP模式是一种层次结构,共分为四层。

 

两个高级协议:传输控制协议(Transmission Control Protocal,TCP)和用户数据报协议(User Datagram Protocal,UDP)

TCP协议是一种以固接连线为基础的协议,它提供两台计算机间可靠的数据传送。TCP可以保证从一端数据送至连接的另一端时,数据能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同,因此,TCP协议适合可靠性要求比较高的场合。(拨打电话)

UDP是无连接通信协议,不保证可靠数据传输,但能够向若干个目标发送数据,接收发自若干个源的数据。UDP是以独立发送数据包的方式进行。(邮递员送信)UDP协议适合对数据准确性要求不高的场合。

端口:一般而言,一台计算机只有单一的连到网络的物理连接,所有的数据都通过此连接对内、对外送达特定的计算机。网络程序设计中的端口并非真实的物理存在,而是一个假想的连接装置。规定0~65535之间的整数。HTTP服务一般使用80端口,FTP服务使用21端口。客户机通过不同的端口来确定连接到服务器的哪项服务。

套接字:网络程序中的套接字(Socket)用于将应用程序与端口连接起来。是一个假想的连接装置。就像插座用于连接电器与电线

 

TCP程序设计

InetAddress类

java.net.Address类与IP地址相关,利用该类获取IP地址、主机地址等信息

  • getByName(String host)---获取与Host相应的的InetAddress对象

  • getHostAddress()---获取InetAddress对象所含的IP地址

  • getHostName()---获取此IP地址的主机名

  • getLocalHost()---返回本地主机的InetAddress对象

ServerSocket类

java.net.ServerSocket类用来表示服务器套接字,其主要功能是等待来自网络上的“请求”,它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入队列中,然后取出一个套接字与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的请求被拒绝。队列的默认大小为50。

构造函数(都抛出IOException)

  • ServerSocket()---创建非绑定服务器套接字

  • ServerSocket(int port)---创建绑定到特定端口的服务器套接字

  • ServerSocket(int port,int backlog)---利用指定的backlog创建服务器套接字并将其绑定到指定的本地端口号

  • ServerSocket(int port,int backlog,InetAddress bindAddress)---利用指定的端口、侦听backlog和要绑定到本地IP地址创建服务器。适用于计算机有多块网卡和多个IP地址的情况,用于明确在哪块网卡或IP地址上等待客户的连接请求

常用方法

  • accep()---等待客户机的连接,若连接则创建一套接字

  • isBound()---判断ServerSocket的绑定状态

  • getInetAddress()---返回此服务器套接字的本地地址

  • isClosed()---返回服务器套接字的关闭状态

  • close()---关闭服务器套接字

  • bind(SocketAddress endpoint)---将ServerSocket绑定到特定地址(IP地址和端口号)

  • getPort()----返回此套接字连接到的远程端口

服务器端和客户端交互过程

  • 服务器程序创建一个ServerSocket服务器端套接字,调用accept()方法等待客户机来连接

  • 客户端程序创建一个Socket,请求与服务器建立连接

  • 服务器接收客户机的连接请求,同时创建一个新的Socket与客户建立连接。服务器继续等待新的请求

//实现TCP单向通信
public class MyTcp {  //服务器端程序
    private BufferedReader render;  //字符输入流
    private ServerSocket server;  //服务器端套接字
    private Socket socket;  //客户端套接字
    void getserver(){
        try{
            server = new ServerSocket(8998);  //实例化Socket对象
            System.out.println("服务器套接字创建成功");
            while(true){
                System.out.println("等待客户机连接");
                socket = server.accept();
                render = new BufferedReader(new InputStreamReader(socket.getInputStream())); //服务器通过输入流接收数据
                getClientMessage();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //获取客户端信息
    private void getClientMessage(){
        try{
            while(true){ //如果套接字是连接状态
                System.out.println("客户机:"+render.readLine());
            }
        }catch(Exception e){
           e.printStackTrace();
        }
        try{
            if(render!=null){  //关闭流
                render.close();
            }
            if(socket!=null){ //关闭套接字
                socket.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        MyTcp tcp = new MyTcp();
        tcp.getserver();  //调用方法
    }
}
public class MyClient extends JFrame {  //客户端程序
    private PrintWriter writer;  //字符输出流
    Socket socket;  //客户端套接字
    private JTextArea ta = new JTextArea();
    private JTextField tf = new JTextField();
    Container cc;
    public MyClient(String title){  //构造方法
        super(title);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cc = this.getContentPane();
        final JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
        getContentPane().add(scrollPane,BorderLayout.CENTER);
        scrollPane.setViewportView(ta);
        cc.add(tf,"South");   //将文本框放在窗体的下部
        tf.addActionListener(new ActionListener() { //绑定事件
            @Override
            public void actionPerformed(ActionEvent e) {
                writer.println(tf.getText());  //将文本框中的信息写入流
                ta.append(tf.getText()+'\n');  //将文本框中的信息显示在文本域中
                ta.setSelectionEnd(ta.getText().length());
                tf.setText("");  //将文本框清空
            }
        });
    }
    private void connect(){
        ta.append("尝试连接\n"); //文本域中提示信息
        try{
            socket = new Socket("127.0.0.1",8998);  //实例化Socket
            writer = new PrintWriter(socket.getOutputStream(),true);  //客户机通过输出流发送数据
            ta.append("完成连接\n");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        MyClient client = new MyClient("向服务器发送数据");
        client.setSize(300,250);
        client.setVisible(true);
        client.connect();
    }
}
运行服务器,再运行客户端,建立连接,向文本框输入信息,输入信息在服务器端输出。

UDP程序设计

基于UDP的信息传递快,但不提供可靠的保证。使用UDP传递数据时,用户无法知道数据能否到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。

基于UDP通信的基本模式:

  • 将数据打包(称为数据包),然后将数据包发往目的地

  • 接收别人发来的数据包,然后查看数据包

发送数据包:

  • 使用DatagramSocket()创建一个数据包套接字

  • 使用DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)创建要发送的数据包

  • 使用DatagramSocket类的send()方法发送数据包

接收数据包:

  • 使用DatagramSocket(int port)创建数据包套接字,绑定到指定端口

  • 使用DatagramPacket(byte[] buf,int length)创建字节数组来接收数据包

  • 使用DatagramPacket类的receive()方法接收UDP包

DatagramPacket类

java.net包中的DatagramPacket类表示数据包。

构造方法

  • DatagramPacket(byte[] buf,int length)---创建DatagramPacket对象,指定内存空间和大小

  • DatagramPacket(byte[] buf,int length,InetAddress address,int port)--创建DatagramPacket对象,指定内存空间、大小、数据包的目标地址和端口(在发送数据时,必须指定接收方的Socket地址和端口号,所以使用此构造方法创建发送数据的DatagramPacket对象)

DatagramSocket类

java.net包中的DatagramSocket类用于表示发送和接收数据包的套接字

构造方法

  • DatagramSocket() -- 创建DatagramSocket对象,构造数据报套接字并将其绑定到本地主机上任何可用的端口

  • DatagramSocket(int port)-- 创建DatagramSocket对象,构造数据报套接字并将其绑定到本地主机上指定的端口(接收程序)

  • DatagramSocket(int port,InetAddress addr)-- 创建DatagramSocket对象,构造数据报套接字并将其绑定到指定的本地地址,适用于有多块网卡和多个IP地址的情况


篇幅过长了~  更多练习代码见链接

https://gitee.com/chen-xing1/java-study.githttps://gitee.com/chen-xing1/java-study.git

 

Guess you like

Origin blog.csdn.net/acx0000/article/details/128007969