【Java高级】枚举、泛型、注解、反射、异常处理、多线程、IO流

文章目录

  • 一.枚举
    • 1.1内部类中使用枚举
    • 1.2迭代枚举元素
    • 1.3在Switch中使用枚举类
    • 1.4values(), ordinal() 和 valueOf() 方法
    • 1.5枚举类成员
  • 二.泛型
    • 2.1.泛型方法
      • 泛型标记符
    • 2.2实例
    • 2.3泛型类
      • 实例
    • 2.4类型通配符
  • 三.注解与反射
    • 3.1注解
      • 3.1.1什么是注解
      • 3.1.2内置注解
      • 3.1.3元注解
      • 3.1.4自定义注解
    • 3.2反射
  • 四.异常处理
    • 4.1异常的概述
    • 4.2异常的处理
    • 4.3异常的相关关键字介绍
      • throws关键字:
      • throw关键字:
      • finally关键字:
    • 4.4自定义异常实现
  • 五.多线程
    • 1.线程简介
    • 2.线程实现(重点)
      • Thread:
      • Runnable:
      • 并发问题:
      • 例子:龟兔赛跑
      • Callable接口:
      • 静态代理模式
      • Lambda表达式
    • 3.线程状态
      • 线程停止
      • 线程休眠(sleep)
      • 线程礼让 (yield)
      • 线程强制执行 (join)
      • 线程线程测状态
    • 4.线程优先级
    • 5.守护(daemon)线程
    • 6.线程同步(synchronized)
      • 一.同步方法:
      • 二.同步代码快
      • 三.死锁
      • 四.Lock锁
      • 五.线程协作
        • 管程法:
        • 信号灯法:
    • 7.线程池
  • 六.IO流

一.枚举

Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一年的 12 个月份,一个星期的 7 天,方向有东南西北等。

Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。

例如定义一个颜色的枚举类。

enum Color 
{
    
    RED, GREEN, BLUE; 
} 

以上枚举类 Color 颜色常量有 RED, GREEN, BLUE,分别表示红色,绿色,蓝色。

enum Color 
{
    
    RED, GREEN, BLUE; 
} 
  
public class Test 
{
    
    // 执行输出结果
    public static void main(String[] args) 
    {
    
        Color c1 = Color.RED; 
        System.out.println(c1);   //RED
    } 
}

1.1内部类中使用枚举

public class Test 
{
    
    enum Color 
    {
    
        RED, GREEN, BLUE; 
    } 
  
    // 执行输出结果
    public static void main(String[] args) 
    {
    
        Color c1 = Color.RED; 
        System.out.println(c1);   //RED
    } 
}

每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的。

以上的枚举类 Color 转化在内部类实现:

class Color
{
   
     public static final Color RED = new Color();
     public static final Color BLUE = new Color();
     public static final Color GREEN = new Color();
}

1.2迭代枚举元素

可以使用 for 语句来迭代枚举元素:

enum Color 
{
    
    RED, GREEN, BLUE; 
} 
public class MyClass {
    
  public static void main(String[] args) {
    
    for (Color myVar : Color.values()) {
   
      System.out.println(myVar);
    }
  } 
}
//RED
//GREEN
//BLUE

1.3在Switch中使用枚举类

枚举类常应用于 switch 语句中:

enum Color 
{
    
    RED, GREEN, BLUE; 
} 
public class MyClass {
   
  public static void main(String[] args) {
   
    Color myVar = Color.BLUE;

    switch(myVar) {
   
      case RED:
        System.out.println("红色");
        break;
      case GREEN:
         System.out.println("绿色");
        break;
      case BLUE:
        System.out.println("蓝色");
        break;
    }
  }
}

//输出结果:
蓝色

1.4values(), ordinal() 和 valueOf() 方法

enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。
enum Color 
{
    
    RED, GREEN, BLUE; 
} 
  
public class Test 
{
    
    public static void main(String[] args) 
    {
    
        // 调用 values() 
        Color[] arr = Color.values(); 
  
        // 迭代枚举
        for (Color col : arr) 
        {
    
            // 查看索引
            System.out.println(col + " at index " + col.ordinal()); 
        } 
  
        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException 
        System.out.println(Color.valueOf("RED")); 
        // System.out.println(Color.valueOf("WHITE")); 
    } 
}

//输出结果;
RED at index 0
GREEN at index 1
BLUE at index 2
RED

1.5枚举类成员

枚举跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所以外部无法调用。

枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

enum Color 
{
    
    RED, GREEN, BLUE; 
  
    // 构造函数
    private Color() 
    {
    
        System.out.println("Constructor called for : " + this.toString()); 
    } 
  
    public void colorInfo() 
    {
    
        System.out.println("Universal Color"); 
    } 
} 
  
public class Test 
{
        
    // 输出
    public static void main(String[] args) 
    {
    
        Color c1 = Color.RED;   //这里只调用RED实例,结果输出三个,因为如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它
        System.out.println(c1); 
        c1.colorInfo(); 
    } 
}

//输出结果;
Constructor called for : RED
Constructor called for : GREEN
Constructor called for : BLUE
RED
Universal Color

二.泛型

  • Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

    泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

  • 假定我们有这样一个需求:写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,该如何实现?

    答案是可以使用 Java 泛型

    使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序。然后,调用该泛型方法来对整型数组、浮点数数组、字符串数组等进行排序。

2.1.泛型方法

可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

下面是定义泛型方法的规则:

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 )。
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。

泛型标记符

java 中泛型标记符:

  • E - Element (在集合中使用,因为集合中存放的是元素)
  • T - Type(Java 类)
  • K - Key(键)
  • V - Value(值)
  • N - Number(数值类型)
  • - 表示不确定的 java 类型

2.2实例

下面的例子演示了如何使用泛型方法打印不同类型的数组元素:

public class GenericMethodTest
{
   
   // 泛型方法 printArray                         
   public static < E > void printArray( E[] inputArray )
   {
   
      // 输出数组元素            
         for ( E element : inputArray ){
           
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] )
    {
   
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = {
    1, 2, 3, 4, 5 };
        Double[] doubleArray = {
    1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = {
    'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

//输出结果:
整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O 

2.3泛型类

  • 泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

    和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

    实例

    public class Box<T> {
         
       
      private T t;
     
      public void add(T t) {
         
        this.t = t;
      }
     
      public T get() {
         
        return t;
      }
     
      public static void main(String[] args) {
         
        Box<Integer> integerBox = new Box<Integer>();
        Box<String> stringBox = new Box<String>();
     
        integerBox.add(new Integer(10));
        stringBox.add(new String("菜鸟教程"));
     
        System.out.printf("整型值为 :%d\n\n", integerBox.get());
        System.out.printf("字符串为 :%s\n", stringBox.get());
      }
    }
    
    //输出结果:
    整型值为 :10
    
    字符串为 :菜鸟教程
    
    

2.4类型通配符

1、类型通配符一般是使用 ? 代替具体的类型参数。例如 List 在逻辑上是 List,List 等所有 List<具体类型实参> 的父类。

import java.util.*;
 
public class GenericTest {
   
     
    public static void main(String[] args) {
   
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        getData(name);
        getData(age);
        getData(number);
       
   }
 
   public static void getData(List<?> data) {
   
      System.out.println("data :" + data.get(0));
   }
}

//输出结果:
data :icon
data :18
data :314

解析: 因为 getData() 方法的参数是 List 类型的,所以 name,age,number 都可以作为这个方法的实参,这就是通配符的作用。

2、类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。

import java.util.*;
 
public class GenericTest {
   
     
    public static void main(String[] args) {
   
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        
        name.add("icon");
        age.add(18);
        number.add(314);
 
        //getUperNumber(name);//1
        getUperNumber(age);//2
        getUperNumber(number);//3
       
   }
 
   public static void getData(List<?> data) {
   
      System.out.println("data :" + data.get(0));
   }
   
   public static void getUperNumber(List<? extends Number> data) {
   
          System.out.println("data :" + data.get(0));
       }
}

//输出结果:
data :18
data :314

解析://1 处会出现错误,因为 getUperNumber() 方法中的参数已经限定了参数泛型上限为 Number,所以泛型为 String 是不在这个范围之内,所以会报错。

3、类型通配符下限通过形如 List 来定义,表示类型只能接受 Number 及其上层父类类型,如 Object 类型的实例。

三.注解与反射

3.1注解

  • Annotation是从JDK5.0开始引入的技术

  • Annotation的作用:

    • 不是程序本身,可以对程序做出解释(这一点和注释(comment)没什么区别)
    • 可以被其他程序(比如:编译器等)读取
  • 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarning(Values=“zheshizhujie”),

  • Annotation在哪里使用?

    • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

3.1.1什么是注解

public class Test01 extends Object{
   

    @Override   //重写注解
    public String toString() {
   
        return super.toString();
    }
}

3.1.2内置注解

  1. @Override:定义在java.lang.Override中,表示一个方法声明打算重写超类中的另一个方法声明
  2. @Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择
  3. @SuppressWarning:定义在java.lang.SuppressWarning中,用来镇压编译时的警告信息
import java.util.ArrayList;
import java.util.List;

public class Test01 extends Object{
   

    @Override   //重写注解
    public String toString() {
   
        return super.toString();
    }

    @Deprecated
    public static void test(){
   
        System.out.println("这是Deprecated");
    }
    @SuppressWarnings("all")
    public void test02(){
   
        List list = new ArrayList();
    }


    public static void main(String[] args) {
   
        test();
    }
}

3.1.3元注解

  • 作用:负责注解其他注解,java定义了4个标准的meta—annotation类型,他们被用来提供对其他annotation类型作说明
  • 这些类型和他们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
    • @Target:用于描述注解的适用范围(即:被描述的注解可以用在什么地方)
    • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
      • (SOURCE
    • @Documented:说明该注释将被包含在javadoc中
    • @Inherited:说明子类可以继承父类中的该注解
import java.lang.annotation.*;

//测试元注解
@Test02.MyAnnotation
public class Test02 {
   
    public void test(){
   

    }
//定义一个注解
//Target  表示我们的注解可以用在哪些地方
    @Target(value = {
   ElementType.METHOD,ElementType.TYPE})

//Retention  表示我们的注解在什么地方还有效
// runtime>class>source
    @Retention(value = RetentionPolicy.RUNTIME)

//Documented 表示是否将我们的注解生成在javadoc中
    @Documented

//Inherited  子类可以继承父类的注解
    @Inherited
    @interface MyAnnotation{
   

    }
}

3.1.4自定义注解

  • Java中的自定义注解允许开发者定义自己的注解类型,以便在代码中使用。自定义注解可以用于提供元数据,这些元数据可以在编译时或运行时被工具、框架或应用程序读取和处理。

要定义一个自定义注解,你需要使用@interface关键字。下面是一个简单的自定义注解的例子:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 定义注解的保留策略
@Retention(RetentionPolicy.RUNTIME)
// 定义注解可以应用的目标元素类型
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
   
    // 定义注解的属性
    String value() default "";
    int count() default 0;
}

在这个例子中,我们定义了一个名为MyCustomAnnotation的自定义注解。这个注解有两个属性:value和count。value属性默认为空字符串,cou

你可能感兴趣的:(Java,java,开发语言,java-ee,intellij-idea)