当前位置: 首页 > news >正文

16Java基础之枚举、泛型、API、Objects类、包装类

枚举

  • 枚举是一种特殊类。
  • 枚举类的格式:
    修饰符 enum 枚举类名{
    名称1,名称2...;
    其他成员...
    }

注意:

  1. 枚举类中的第一行,只能写一些合法的标识符(名称),多个名称用逗号隔开。
  2. 这些名称,本质是常量,每个常量都会记住枚举类的一个对象

案例:

// 枚举类
public enum A {// 枚举类的第一行必须罗列的是枚举对象的名称X, Y, Z;// 其他成员private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}测试方法:
// 目标:认识枚举类,搞清楚枚举类的特点
public class Test {public static void main(String[] args) {// 枚举无法创建对象,构造器是私有的
//        A a = new A();A a1 = A.X;A a2 = A.Y;System.out.println(a1);System.out.println(a2);System.out.println("---------------------------");//编译器为枚举类新增了几个方法//拿到枚举类的全部对象,放到一个数组中返回。A[] as = A.values();for (int i = 0; i < as.length; i++) {A a = as[i];System.out.println(a);}//拿到X的枚举对象A y = A.valueOf("X");System.out.println(y == a1);// ordinal,拿对象的索引System.out.println(a1.ordinal());System.out.println(a2.ordinal());}
}输出结果:
X
Y
---------------------------
X
Y
Z
true
0
1

image

  • 上图为枚举类反编译后的代码截图。

枚举的特点

  1. 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。
  2. 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。
  3. 枚举类中,从第二行开始,可以定义类的其他各种成员。
  4. 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法。

枚举的应用场景

  • 枚举通常用来表示一组信息,然后作为参数进行传输。

选择定义一个一个的常量来表示一组信息,并作为参数传递,参数值不受约束。
选择定义枚举表示一组信息,并作为参数传递,代码可读性好,参数值得到了约束,对使用者更友好,建议使用。
案例:

需求:需要提供一个方法,可以完成向下取整,向上取整,四舍五入,去掉小数部分。
如果用常量来表示一组功能信息,代码如下:
常量类:
// 常量类
public class Constant {public static final int DOWN = 1;public static final int UP = 2;public static final int HAFL_UP = 3;public static final int INT = 4;
}
测试方法:
// 目标:搞清楚枚举的应用场景:信息标志和信息分类
public class Test {public static void main(String[] args) {// 需求:需要提供一个方法,可以完成向下取整,向上取整,四舍五入,去掉小数部分。// 常量信息标准和分类:参数值不被约束。System.out.println(handleData(3.768, Constant.DOWN));System.out.println(handleData(3.768, Constant.UP));}public static double handleData(double number,int type){switch(type){case Constant.DOWN:// 向下取整number = Math.floor(number);break;case Constant.UP:// 向上取整number = Math.ceil(number);break;case Constant.HAFL_UP:// 四舍五入number = Math.round(number);break;case Constant.INT:// 去掉小数部分number = (int)number;break;default:System.out.println("输入的类型有误");}return number;}
}
//----------------------------------------------------
如果使用枚举,代码如下:
枚举类:
public enum Constant2 {DOWN,UP,HAFL_UP,INT;
}测试方法:
public class Test2 {public static void main(String[] args) {// 需求:需要提供一个方法,可以完成向下取整,向上取整,四舍五入,去掉小数部分。// 枚举做信息标准和分类:参数值被约束,最好的信息标志和分类的理想方案。System.out.println(handleData(3.768, Constant2.DOWN));System.out.println(handleData(3.768, Constant2.UP));}public static double handleData(double number,Constant2 type){switch(type){case Constant2.DOWN:// 向下取整number = Math.floor(number);break;case Constant2.UP:// 向上取整number = Math.ceil(number);break;case Constant2.HAFL_UP:// 四舍五入number = Math.round(number);break;case Constant2.INT:// 去掉小数部分number = (int)number;break;default:System.out.println("输入的类型有误");}return number;}
}注意:handleData方法中的,Constant2.是可以省略的。

泛型

  • 在定义类、接口、方法是,同时声明了一个或多个类型变量(如:“”),称为泛型类、泛型接口、泛型方法,它们统称为泛型。
    image

  • 作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。

  • 泛型的本质:把具体的数据类型作为参数传给变量。


案例:

// 目标:认识泛型
public class Test {public static void main(String[] args) {ArrayList list = new ArrayList();list.add("魔法");list.add("霍格沃兹");list.add("我是一个中国人");list.add(true);list.add(123);list.add(12.23);// 1. 开发中很多时候需要统一的数据类型。(如果不使用泛型,类型没办法统一,就需要类型转换,容易出现bug)for (int i = 0; i < list.size(); i++) {Object object = list.get(i);String st = (String)object;// 强制类型转换,编译不报错,运行报错。System.out.println(st);}System.out.println("------------------");ArrayList<String> list2 = new ArrayList<>(); //JDK1.7开始,后面类型可以不写list2.add("魔法");list2.add("霍格沃兹");list2.add("我是一个中国人");
//        list2.add(true); // 报错
//        list2.add(123);  // 报错
//        list2.add(12.23);// 报错}
}

泛型类

  • 格式:
    修饰符 class 类名<类型变量,类型变量,……>{
    ……
    }
    举例:
public class ArrayList<E>{……
}

注意:类型变量建议用大写的英文字母,常用的有E、T、K、V等。

  • E‌:通常代表Enum类型,用于表示枚举类型。 ‌
    ‌ - T‌:代表Type类型,常用于泛型类或方法中表示类型参数。 ‌
    ‌ - K‌:代表Key类型,通常用于表示键或标识符。 ‌
    ‌- V‌:代表Value类型,用于表示值或数据

案例

import java.util.ArrayList;// 泛型类
public class MyArrayList<E> {private ArrayList list = new ArrayList();public boolean add(E e){list.add(e);return true;}public boolean remove(E e){return list.remove(e);}@Overridepublic String toString(){return list.toString();}
}

泛型接口

  • 格式
    修饰符 interface接口名<类型变量,类型变量,……>{
    ……
    }
    举例:
    public interface A{
    ……
    }

案例:

// 需求:必须完成学生、老师数据的增删改查操作。
学生类:
public class Student {}
老师类:
public class Teacher {}
泛型接口:
// 泛型接口
//T : 表示泛型的类型,是一个占位符,在编译期会被替换为具体的类型
public interface Data<T> {void add(T t);void remove(T t);void update(T t);T get(int index);
}
学生实现类:
public class DataStudent implements Data<Student>{@Overridepublic void add(Student student) {}@Overridepublic void remove(Student student) {}@Overridepublic void update(Student student) {}@Overridepublic Student get(int index) {return null;}
}
老师实现类:
public class DataTeacher implements Data<Teacher>{@Overridepublic void add(Teacher teacher) {}@Overridepublic void remove(Teacher teacher) {}@Overridepublic void update(Teacher teacher) {}@Overridepublic Teacher get(int index) {return null;}
}
测试方法:
// 目标:认识泛型接口的使用框架
public class Test {public static void main(String[] args) {// 需求:必须完成学生、老师数据的增删改查操作。Student s1 = new Student();Data data = new DataStudent();data.add(s1);data.remove(s1);data.update(s1);data.get(1);}
}

泛型方法、泛型通配符、上下限

泛型方法

  • 格式
    修饰符<类型变量,类型变量,……> 返回值类型 方法名(形参){}
    举例: public static void test(T t){}

案例:

学生类:
public class Student{}测试方法:
// 目标:认识泛型方法
public class Test {public static void main(String[] args) {//需求:要求接收任意对象数组String[] name = {"刘德华", "郭富城", "黎明", "张学友" };Student[] students = new Student[50];printarray(name);printarray(students);}// 泛型方法// 返回值也是泛型,这样可以避免类型转换public static <T> T printarray(T[]array){return array[0];}
}

通配符

  • 就是"?", 可以在"使用泛型"的时候代表一切类型;ETKV是在定义泛型的时候使用。

泛型的上下限

  • 泛型上限:?extends Car: ? 能接收的必须是Car或者其子类。
  • 泛型下限:? super Car: ? 能接收的必须是Car或者其父类。

案例

// 目标:通配符和上下限
public class Test2 {public static void main(String[] args) {// 需求:所有汽车要一起参与比赛。ArrayList<BMW> bmws = new ArrayList<BMW>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());ArrayList<Benz> benzs = new ArrayList<Benz>();benzs.add(new Benz());benzs.add(new Benz());benzs.add(new Benz());// 正常是送车的集合,结果送成狗了,但程序依然可以运行,这是有bug的
//        ArrayList<Dog> dogs = new ArrayList<Dog>();
//        dogs.add(new Dog());
//        dogs.add(new Dog());
//        dogs.add(new Dog());
//        go(dogs);go(bmws);go(benzs);}// 虽然BMW和Benz都是Car的子类,但是ArrayList<BMW>、ArrayList<Benz>、ArrayList<Car>并不是同一个类型// 通配符:其实就是?,可以使用泛型的时候代表一切类型。ETKV是在定义时使用,而?是在使用时使用// 泛型的上下限:? extends Car(上限,?必须是Car或者Car的子类),? super Car(下限,?必须是Car或者Car的父类)//public static void go(ArrayList<BMW> cars){//public static void go(ArrayList<?> cars){public static void go(ArrayList<? extends Car> cars){}
}class Car{}
class BMW extends Car{}
class Benz extends Car{}class Dog{}

泛型的注意事项:擦除问题、基本数据类型问题

  • 泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型的擦除。
  • 泛型不能直接支持基本数据类型,只能支持对象类型(引用数据类型)

API

什么是API?

  • API(Application Programming interface):应用程序编程接口。
  • 就是Java帮我们已经写好一些程序,如:类、方法等,我们直接拿过来用就可以解决一些问题。

为什么要学别人写好的程序?

  • 提高开发效率。

Object类的作用:

  • Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Objcet类中提供的一些方法。

Objcet类的常见方法
image

toString存在的意义:toString默认返回的地址形式其实没什么意义,开发中输出对象更想看内容,因此toString是为了让子类重写
equals存在的意义:equals方法默认是比较两个对象的地址是否一样。比较两个对象的地址是否一致,可以直接使用“==”来比较,完全没必要使用equals。因此,Object提供的equals方法的意义是为了让子类重写,以便子类自己来定义比较规则(按照内容比较)。

案例:

学生类:
import java.util.Objects;public class Student {private String name;private int age;private String score;public Student() {}public Student(String name, int age, String score) {this.name = name;this.age = age;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getScore() {return score;}public void setScore(String score) {this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score='" + score + '\'' +'}';}@Overridepublic boolean equals(Object o) {// 1.判断两个对象是否是同一个对象在比较,如果是,返回trueif (this == o) return true;// 2. 判断o如果是null,或者两个对象的类型不一样,直接返回falseif (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name) && Objects.equals(score, student.score);}@Overridepublic int hashCode() {return Objects.hash(name, age, score);}
}测试方法:
// 目标:掌握object的常用方法。
public class Test {public static void main(String[] args) {Student s1 = new Student("小昭", 18, "100");// 1.toString默认返回的地址形式其实没什么意义,开发中输出对象更想看内容,因此toString是为了让子类重写//System.out.println(s1.toString());//直接输出对象时,toString方法可以不写System.out.println(s1);System.out.println("-----------------------------");// 2.equals方法默认是比较两个对象的地址是否一样。// 比较两个对象的地址是否一致,可以直接使用“==”来比较,完全没必要使用equals。// 因此,Object提供的equals方法的意义是为了让子类重写,以便子类自己来定义比较规则(按照内容比较)。Student s2 = new Student("郡主", 20, "97");Student s3 = new Student("郡主", 20, "97");System.out.println(s2.equals(s3));}
}

Objects

  • Object是一个工具类,提供了很多操作对象的静态方法给我们使用。

案例:

学生类:
import java.util.Objects;public class Student {private String name;private int age;private String score;public Student() {}public Student(String name, int age, String score) {this.name = name;this.age = age;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getScore() {return score;}public void setScore(String score) {this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score='" + score + '\'' +'}';}@Overridepublic boolean equals(Object o) {// 1.判断两个对象是否是同一个对象在比较,如果是,返回trueif (this == o) return true;// 2. 判断o如果是null,或者两个对象的类型不一样,直接返回falseif (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name) && Objects.equals(score, student.score);}@Overridepublic int hashCode() {return Objects.hash(name, age, score);}
}测试:
// 目标:掌握object的常用方法。
public class Test {public static void main(String[] args) {Student s1 = new Student("小昭", 18, "100");// 1.toString默认返回的地址形式其实没什么意义,开发中输出对象更想看内容,因此toString是为了让子类重写//System.out.println(s1.toString());//直接输出对象时,toString方法可以不写System.out.println(s1);System.out.println("-----------------------------");// 2.equals方法默认是比较两个对象的地址是否一样。// 比较两个对象的地址是否一致,可以直接使用“==”来比较,完全没必要使用equals。// 因此,Object提供的equals方法的意义是为了让子类重写,以便子类自己来定义比较规则(按照内容比较)。Student s2 = new Student("郡主", 20, "97");Student s3 = new Student("郡主", 20, "97");System.out.println(s2.equals(s3));System.out.println("---------------------------------------");Student s4 = null;Student s5 = new Student("陈昆", 18, "78");System.out.println(s4.equals(s5)); // 如果主调对象是null,直接就会报空指针异常。// 今后System.out.println(Objects.equals(s4, s5)); // 更安全,更可靠的解决空指针异常}
}

包装类

为什么要有包装类?

  • 包装类就是把基本类型的数据包装成对象。
    image

包装类的其他基本操作

  • 可以把基本类型的数据转换成字符串类型。
    public static String toString(double d)
    public String toString()

  • 可以把字符串类型的数值转换成数值本身对应的数据类型。
    public static int parseInt(String s)
    public static Integer valueOf(String s)

案例:

// 目标:认识包装类,搞清楚他的作用
public class Test {public static void main(String[] args) {// 1. 把基本类型通过包装类包装成对象int a = 10;//        Integer it = new Integer(a);Integer it = Integer.valueOf(a);//手动包装System.out.println(it);// 2. 自动装箱机制,会把基本类型的数据可以直接变成对象赋值给包装类。Integer it2 = 12;Integer it3 = 12;System.out.println(it2 == it3);// 3. 自动拆箱机制,把包装类的对象直接变成基本类型的数据。int it4 = it2;System.out.println(it4);System.out.println("--------------Java为包装类提供了新功能----------------");//1. 功能1:包装类可以把基本类型的数据转换成字符串int a1 = 123;System.out.println(Integer.toString(a1));String rs = a1 + ""; //这种方式简单,但是效率低,底层是通过StringBuilder实现的。System.out.println(rs);// 功能2:把字符串类型的数字转换成基本类型的数据(很有用)String agestr = "23";int a2 = Integer.parseInt(agestr);String corcestr = "87.2";double a3 = Double.parseDouble(corcestr);a2 = Integer.valueOf(agestr);a3 = Double.valueOf(agestr);//3.由于泛型和集合都不支持基本数据类型,因为万物皆对象,因此包装类在集合和泛型中大量使用,而且必须使用。}
}

总结:

  • Integer.valueOf(a)方法中,会自动创建-128~127的类,在这个区间内的对象都一样,超过这个值会新建对象。
  • 由于泛型和集合都不支持基本数据类型,因为万物皆对象,因此包装类在集合和泛型中大量使用,而且必须使用。
http://www.sczhlp.com/news/258.html

相关文章:

  • 卷积神经网络的验证码识别系统设计与实现
  • Git 提交信息(Commit Message)前缀规范
  • Visual Studio中的常用调试功能(二)
  • 易基因突破创新 自主研发DNA甲基化年龄预测算法及系统获发明专利授权
  • 从独立工具到协作中枢:Bug管理系统的进化革命
  • Redis的引入与配置
  • 给删除增加删除感
  • 卷积神经网络的验证码识别系统设计
  • scrollTop
  • 阿里云OSS 的Content-Disposition不生效 导致浏览器强制下载而不是预览行为
  • 测试
  • AI测试开发私教服务全新升级
  • 10分钟无痛部署!字节Coze开源版喂饭教程
  • 28 位运算
  • Prime Video如何将时间序列异常转化为可操作警报
  • 抗原设计与合成服务|定制抗原技术|高效多肽合成
  • 中日甲午海战军舰情况
  • 面试算法练习-更新ing
  • 2025年优选代码托管平台指南
  • 重塑应用搜索体验,系统级入口功能一步直达
  • MATLAB实现不同型号飞机的红外图像识别
  • 我的手机微信开启了一个端口,虽然我不知道是做什么的
  • 构建之法读后感
  • UI总改版?这个自我修复的AI测试神器让团队告别深夜紧急回滚
  • 低分辨率显示器下的样式兼容
  • javascript的BOM对象的详细解析
  • 企业级知识管理系统的进化:从工具选择到效能提升
  • C/C++通过SQLiteSDK增删改查
  • 深入理解 LangGraph:构建复杂智能体的状态管理与执行流
  • ./build.sh:行1: g++: 未找到命令的错误问题在centos操作系统下面如何解决