枚举类的使用

 

1.1 枚举类的理解

/* 一、枚举类:类的对象只有有限个,确定的。
*
* 二、举例如下:
* 星期:Monday(星期一)、......、Sunday(星期天)
* 性别:Man(男)、Woman(女)
* 季节:Spring(春节)......Winter(冬天)
* 支付方式:Cash(现金)、WeChatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、CreditCard(信用卡)
* 就职状态:Busy、Free、Vocation、Dimission
* 订单状态:Nonpayment(未付款)、Paid(已付款)、Delivered(已发货)、Return(退货)、Checked(已确认)、Fulfilled(已配货)
* 线程状态:创建、就绪、运行、阻塞、死亡
*
* 三、当需要定义一组常量时,强烈建议使用枚举类
*
* 补充:如果枚举类的对象只有一个,则也是单例模式的体现。
*/

1.2 如何创建枚举类

* 方式一:自定义类的方式
* 方式二:使用enum关键字 (jdk5.0)
  • 方式一

public class EnumTest {
   public static void main(String[] args) {
       Season spring = Season.SPRING;
       System.out.println(spring);
       System.out.println(spring.getSeasonName());
       System.out.println(spring.getSeasonDesc());
  }
}

class Season{//季节

   //对象的实例变量
   private final String seasonName;//季节的名称
   private final String seasonDesc;//季节的描述
   //提供私有的构造器
   private Season(String seasonName,String seasonDesc){
       this.seasonName = seasonName;
       this.seasonDesc = seasonDesc;
  }

   //内部提供4个枚举类的对象
   public static final Season  SPRING = new Season("春天","春暖花开");
   public static final Season  SUMMER = new Season("夏天","夏日炎炎");
   public static final Season  AUTUMN = new Season("秋天","秋高气爽");
   public static final Season  WINTER = new Season("冬天","白雪皑皑");

   public String getSeasonName() {
       return seasonName;
  }

   public String getSeasonDesc() {
       return seasonDesc;
  }

   @Override
   public String toString() {
       return "Season{" +
               "seasonName='" + seasonName + '\'' +
               ", seasonDesc='" + seasonDesc + '\'' +
               '}';
  }
}
  • 方式二:

/**
*
* 使用enum定义枚举类
*
* 使用enum定义的枚举类默认继承于ava.lang.Enum类
*
* @author shkstart
* @create 16:57
*/
public class EnumTest1 {

   public static void main(String[] args) {
       Season1 spring = Season1.SPRING;
       System.out.println(spring);

       System.out.println(spring.getClass().getSuperclass());
  }
}

enum Season1{//季节
   //内部提供4个枚举类的对象
   SPRING("春天","春暖花开"),
   SUMMER("夏天","夏日炎炎"),
   AUTUMN("秋天","秋高气爽"),
   WINTER("冬天","白雪皑皑");

   //对象的实例变量
   private final String seasonName;//季节的名称
   private final String seasonDesc;//季节的描述

   //提供私有的构造器
   private Season1(String seasonName,String seasonDesc){
       this.seasonName = seasonName;
       this.seasonDesc = seasonDesc;
  }

   public String getSeasonName() {
       return seasonName;
  }

   public String getSeasonDesc() {
       return seasonDesc;
  }

//   @Override
//   public String toString() {
//       return "Season1{" +
//               "seasonName='" + seasonName + '\'' +
//               ", seasonDesc='" + seasonDesc + '\'' +
//               '}';
//   }
}

1.3 Enum类中的常用方法

与1.4 合并

1.4 枚举类的对象实现接口中的方法

/**
* 一、枚举类的使用
* 1. 枚举类的理解
* 2. 自定义类的方式,体现枚举类
* 3. jdk5.0:使用enum关键字定义
* 4. enum定义的方式中,常用的方法
*     toString():没有重写的情况下,默认返回当前枚举类对象的名字
*     values():返回当前枚举类所有的对象构成的数组
*     valueOf(String name):返回指定名称的枚举类的对象
* 5. 枚举类的对象实现接口的操作
*
*
* @author shkstart
* @create 9:19
*/
public class EnumTest {
   public static void main(String[] args) {
       Season1 summer = Season1.SUMMER;
       System.out.println(summer.getClass().getSuperclass());

       System.out.println(summer.toString());
       System.out.println("##############");
       Season1[] season1s = Season1.values();
       for (int i = 0; i < season1s.length; i++) {
           System.out.println(season1s[i]);

           season1s[i].show();
      }

       System.out.println("##############");
       Season1 winter = Season1.valueOf("WINTER");
       System.out.println(winter);
       //如果枚举类中不存在指定名称的枚举类的对象的话,报IllegalArgumentException
//       winter = Season1.valueOf("WINTER1");

//       summer.show();
  }
}

//enum Season1{//季节
//   //内部提供4个枚举类的对象
//   SPRING,
//   SUMMER,
//   AUTUMN,
//   WINTER;
//
//   //提供私有的构造器
//   private Season1(){
//
//   }
//
//}
interface Info{
   void show();
}

enum Season1 implements Info{//季节
   //内部提供4个枚举类的对象
   SPRING("春天","春暖花开"){
       public void show(){
           System.out.println("春天在哪里?");
      }
  },
   SUMMER("夏天","夏日炎炎"){
       public void show(){
           System.out.println("宁夏");
      }
  },
   AUTUMN("秋天","秋高气爽"){
       public void show(){
           System.out.println("秋天不回来");
      }
  },
   WINTER("冬天","白雪皑皑"){
       public void show(){
           System.out.println("大约在冬季");
      }
  };

   //对象的实例变量
   private final String seasonName;//季节的名称
   private final String seasonDesc;//季节的描述

   //提供私有的构造器
   private Season1(String seasonName,String seasonDesc){
       this.seasonName = seasonName;
       this.seasonDesc = seasonDesc;
  }

   public String getSeasonName() {
       return seasonName;
  }

   public String getSeasonDesc() {
       return seasonDesc;
  }

//   @Override
//   public void show() {
//       System.out.println("这是一个季节");
//   }

}

2. 注解的使用

2.1 注解的理解

/**
* 注解(Annotation)的使用
*
* 1. jdk 5.0的新特性
* 2. Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。
* 3. Annotation 可以像修饰符一样被使用, 可用于修饰包,类, 构造器, 方法, 成员变量, 参数, 局部变量的声明,
*   这些信息被保存在 Annotation 的 “name=value” 对中。

*/
  • 注解的作用

2.2 Java阶段常见注解

在编译时进行格式检查(JDK内置的三个基本注解)
*     @Override: 限定重写父类方法, 该注解只能用于方法
*     @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
*     @SuppressWarnings: 抑制编译器警告

2.3 如何定义注解

参照@SuppressWarnings定义。
/**
* 自定义注解
*
* 说明:
* Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。我们称为配置参数。
* 类型只能是八种基本数据类型、String类型、Class类型、enum类型、Annotation类型、以上所有类型的数组。
*
* @author shkstart
* @create 10:32
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
   String value();
}

2.4 元注解

/* 6. 元注解
*     ① @Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期
*         三种生命周期状态:SOURCE:字节码文件中不保存
*                         CLASS:会保留到字节码文件中,但是运行时内存中不保存。默认行为
*                         RUNTIME:运行时会保留到内存中。 可以后期通过反射获取。
*     ② @Target: 用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。
*     ③ @Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档。
*         默认情况下,javadoc是不包括注解的。
*     ④ @Inherited: 被它修饰的 Annotation 将具有继承性。
*         如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解
*
*
*     上述的元注解中的@Retention、@Target一般在定义注解时,都会使用。
*/

2.5 注解的获取

如何通过反射获取注解信息(在反射章节讲)

3. 程序、进程、线程的理解

4. 如何创建多线程

4.1 继承Thread类

package com.atguigu.java1;

/**
* 创建一个分线程,用于遍历100以内的偶数
*
* 方式一:使用继承Thread类的方式
*
* 1. 创建一个继承于Thread类的子类
* 2. 重写Thread类的run() : 方法体的内容即为当前创建的线程要执行的操作
* 3. 创建子类的对象
* 4. 通过子类对象调用其start(): ① 启动线程 ② 调用当前线程的run()
*
* @author shkstart
* @create 14:17
*/

//1. 创建一个继承于Thread类的子类
class EvenNumber extends Thread {

   int maxNumber;

   public EvenNumber(int maxNumber){
       this.maxNumber = maxNumber;
  }

   //2. 重写Thread类的run()
   @Override
   public void run() {
       //遍历100以内的偶数
       for(int i = 0;i <= maxNumber;i++){
           if(i % 2 == 0){
               System.out.println(i);
          }
      }
  }
}


public class EvenNumberTest {
   public static void main(String[] args) {
       //3. 创建子类的对象
       EvenNumber thread1 = new EvenNumber(100);

       //4. 通过子类对象调用其start()
       thread1.start();

       //问题一:能不能通过直接调用run()的方式替换start(),启动线程? No!
//       thread1.run();

       //问题二:需要再创建一个遍历100以内偶数的线程?如何做?
//       thread1.start();//此时报IllegalThreadStateException异常。

       //正确的:
       EvenNumber thread2 = new EvenNumber(100);
       thread2.start();

       //遍历100以内的偶数
       for(int i = 0;i <= 100;i++){
           if(i % 2 == 0){
               System.out.println(i + "*************");
          }
      }
  }

}

4.2 实现Runnable接口

package com.atguigu.java1;

/**
* 遍历100以内的奇数。
*
* 方式二:实现Runnable接口的方式:
* 1. 提供实现Runnable接口的实现类
* 2. 实现接口中的抽象方法run():方法体的内容即为当前创建的线程要执行的操作
* 3. 创建实现类的对象
* 4. 将实现类的对象作为参数,传递到Thread类的构造器中,创建Thread类的对象
* 5. 通过Thread类的对象调用start():① 启动线程 ② 调用当前线程的run()
*
*
* 对比继承Thread类和实现Runnable接口的方式
* 1. 哪个更好?实现Runnable接口
* 2.
* ① 继承的方式受到类的单继承性的局限性的影响
* ② 对于多个线程操作共享数据的场景,实现的方式更适合。
* ③ 实现的方式更好的体现了数据与操作逻辑的分离。
* 3. 二者的联系:
*   public class Thread implements Runnable
*
* @author shkstart
* @create 15:05
*/
//1. 提供实现Runnable接口的实现类
class OddNumber implements Runnable{
   //2. 实现接口中的抽象方法run()
   @Override
   public void run() {
       for (int i = 0; i <= 100; i++) {
           if(i % 2 != 0){
               System.out.println(i);
          }
      }
  }

}

public class OddNumberTest {

   public static void main(String[] args) {
       //3. 创建实现类的对象
       OddNumber o = new OddNumber();
       //4. 将实现类的对象作为参数,传递到Thread类的构造器中,创建Thread类的对象
       Thread t1 = new Thread(o);
       //5. 通过Thread类的对象调用start()
       t1.start();

       // 再创建一个线程,用于遍历100以内的奇数
       Thread t2 = new Thread(o);
       t2.start();

       System.out.println("========hello========");
  }

}
  • 练习题

package com.atguigu.exer;

/**
* 练习:创建两个分线程,其中一个线程遍历100以内的偶数,另一个线程遍历100以内的奇数?
*
*
*
* @author shkstart
* @create 14:38
*/

class EvenNumber extends Thread{
   @Override
   public void run() {
       for (int i = 0; i <= 100; i++) {
           if(i % 2 == 0){
               System.out.println(i);
          }
      }

  }
}

class OddNumber extends Thread{
   @Override
   public void run() {
       for (int i = 0; i <= 100; i++) {
           if(i % 2 != 0){
               System.out.println(i + "**********");
          }
      }

  }
}

public class NumberTest {
   public static void main(String[] args) {
//       EvenNumber t1 = new EvenNumber();
//       OddNumber t2 = new OddNumber();
//
//       t1.start();
//       t2.start();

       //方式一:创建Thread类的匿名子类的匿名对象
//       new Thread(){
//           @Override
//           public void run() {
//               for (int i = 0; i <= 100; i++) {
//                   if(i % 2 == 0){
//                       System.out.println(i);
//                   }
//               }
//
//           }
//       }.start();
//
//       new Thread(){
//           @Override
//           public void run() {
//               for (int i = 0; i <= 100; i++) {
//                   if(i % 2 != 0){
//                       System.out.println(i + "***************");
//                   }
//               }
//
//           }
//       }.start();

       //方式二:提供Runnable接口匿名实现类的匿名对象
       new Thread(new Runnable(){

           @Override
           public void run() {
               for (int i = 0; i <= 100; i++) {
                   if(i % 2 == 0){
                       System.out.println(i);
                  }
              }
          }
      }).start();

       new Thread(new Runnable(){
           @Override
           public void run() {
               for (int i = 0; i <= 100; i++) {
                   if(i % 2 != 0){
                       System.out.println(i + "***********");
                  }
              }
          }
      }).start();

  }
}
  • 例题

package com.atguigu.java1;

/**
*
* 例题:开启三个窗口售票,总票数为100张。
*
* 使用继承Thread类的方式实现
*
* @author shkstart
* @create 15:26
*/

class Window extends Thread{

   static int ticket = 100;//初始票数100张

   @Override
   public void run() {
       while(true){

           if(ticket > 0){
               System.out.println(Thread.currentThread().getName() + "卖票,当前票号为:" + ticket);
               ticket--;

          }else{
               break;
          }
      }

  }
}

public class WindowTest {
   public static void main(String[] args) {

       Window t1 = new Window();
       Window t2 = new Window();
       Window t3 = new Window();

       t1.start();
       t2.start();
       t3.start();

  }

}
package com.atguigu.java1;

/**
*
* 例题:开启三个窗口售票,总票数为100张。
*
* 使用实现Runnable接口的方式
*
*
* @author shkstart
* @create 15:48
*/

class Window1 implements Runnable{
   int ticket = 100;
   @Override
   public void run() {
       while(true){
           if(ticket > 0){
               System.out.println(Thread.currentThread().getName() + "卖票,当前票号为:" + ticket);
               ticket--;

          }else{
               break;
          }
      }
  }
}

public class WindowTest1 {
   public static void main(String[] args) {
       Window1 w = new Window1();

       Thread t1 = new Thread(w);
       Thread t2 = new Thread(w);
       Thread t3 = new Thread(w);

       t1.start();
       t2.start();
       t3.start();
  }
}
/* 对比继承Thread类和实现Runnable接口的方式
* 1. 哪个更好?实现Runnable接口
* 2.
* ① 继承的方式受到类的单继承性的局限性的影响
* ② 对于多个线程操作共享数据的场景,实现的方式更适合。
* ③ 实现的方式更好的体现了数据与操作逻辑的分离。
* 3. 二者的联系:
*   public class Thread implements Runnable
*/

5. 线程中的常用方法

/**
* 测试Thread类中的常用方法
* 1. run(): 执行分线程的操作
* 2. start(): ① 启动线程 ② 调用线程的run()
* 3. currentThread():获取当前执行代码的线程
* 4. getName():获取线程的名称
* 5. setName():设置线程的名称
* 6. yield():一旦执行此方法,cpu就释放对当前线程的执行。
* 7. join(): 在线程a中调用了线程b的join(),此时线程a进入阻塞状态,直到线程b执行结束之后,才结束阻塞状态继续执行。
* 8. sleep(long millis):静态方法,让当前线程“睡眠”指定的毫秒数
* 9. isAlive():是否存活
*
* 测试线程的优先级:
*
*   getPriority():获取线程的优先级
*   setPriority():设置线程的优先级
*
*   线程的优先级中: MIN_PRIORITY = 1
*                 NORM_PRIORITY = 5 (默认优先级)
*                 MAX_PRIORITY = 10
*
*   理解:高优先级的线程会抢占低优先级的线程的cpu资源。此时的抢占是从概率上来讲,以更高的概率被cpu执行而已。
*
* @author shkstart
* @create 16:20
*/
class EvenNumber extends Thread {
   @Override
   public void run() {
       //遍历100以内的偶数
       for(int i = 0;i <= 100;i++){

           if(i % 2 == 0){

//               try {
//                   Thread.sleep(10);
//               } catch (InterruptedException e) {
//                   e.printStackTrace();
//               }

               System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i);
          }

//           if(i % 20 == 0){
//               this.yield();
//           }
      }
  }
}


public class ThreadMethodTest {
   public static void main(String[] args) {
       EvenNumber thread1 = new EvenNumber();

       thread1.setName("线程1");
       thread1.setPriority(Thread.MAX_PRIORITY);
       thread1.start();

       Thread.currentThread().setName("主线程");
       Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

       //遍历100以内的偶数
       for(int i = 0;i <= 100;i++){
           if(i % 2 == 0){
               System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i);
          }

//           if(i == 40){
//               try {
//                   thread1.join();
//               } catch (InterruptedException e) {
//                   e.printStackTrace();
//               }
//
//           }
      }
//       System.out.println(thread1.isAlive());
  }

}
posted @ 2021-06-16 20:28  我是新平  阅读(90)  评论(0)    收藏  举报