目录
前言:
这篇文章内容比较杂,涉及泛型数组、枚举、反射、对象包装器和自动装箱
一、泛型数组
1.什么是泛型:
泛型就是类型参数化,一提到参数就想到方法的参数,在泛型这里也是这样,把类型参数化,在调用时在具体出来
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中, 操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中
来看下面代码感受一下:
在指定参数类型后,arr1、arr2、arr3就会围绕着各自的参数来进行工作,基本类型作为参数类型时,必须是基本类型的包装类才行,例如int=>Inteegr、double=>Double、........
2.泛型数组ArrayList基本介绍
这里我们重点介绍ArrayList<E>
它的功能类似数组,或者说是数组的遍历版,存储数值都是顺序排放,可以按下标查找,与数组不同的是它在数据量达到阈值时,自动扩容为原来的1.5倍
1)增删改查
public static void main(String[] args) {
ArrayList<Integer> arr = new ArrayList<>();
/**
* 添加
* () -> (1,2,3,4,5)
*/
arr.add(1);
arr.add(2);
arr.add(3);
arr.add(4);
arr.add(5);
/**
* 删除第0号元素
* (1,2,3,4,5) ->(2,3,4,5);
*/
arr.remove(0 );
/**
* 修改:将第3号元素修改为6
* (2,3,4,5) -> (2,3,4,6)
*/
arr.set(3 , 6);
/**
* 查找:查找第0号元素
*/
arr.get(0);
}
2)求长度:
arr.size()
3)foreach遍历
for (int i: arr) {
System.out.println(i);
}
4) 判断是否为空
arr.isEmpty()
二、对象包装器与自动装箱
1.包装器
包装器应用于将基本数据类型转化为对象类型,例如:int 转成 Integer。
包装器类有显而易见的名字:Integer、Double、float、character、Boolean、Short、Byte
2.自动装箱
给包装器类赋值
Integer i = 3;
上面代码,编译器会自动装箱:
//自动装箱过程:
Integer i = Integer。valueOf(3);
3.自动拆箱
包装器给基本类型赋值
Integer i = Integer.valueOf(3);
int j = i;
实际拆箱
int j = i.intValue();
4.比较包装器类
使用equasl比较稳妥
5.补充说明
装箱和拆箱都是编译器的工作,不是Java虚拟机。编译器在生成类的字节码时会插入必要的方法调用。Java虚拟机只是执行这些字节码
Integer对象是不可变的,包含在包装器中的内容不会改变。不能使用这些包装器创建会修改数值参数的方法
public void triple(Integer x){
x = x * 3 //don't work
}
三、参数类型可变的方法
概念: 可以提供参数数量可变的方法,例如:System.out.print("%d %s",n,"Hello,World");
1.方法定义
Java内部的printf是这样定义的
省略号就是代码的一部分,表明可以接收任意数量的对象(fmt参数除外)
以printf为例子,实际上,是接收两个参数,一个是格式字符串,一个是Object[]数组其中保存着所以其他参数,如果是基本数据类型,会被自动装箱
2.实操例子
public static void main(String[] args) {
System.out.println(max(new double[]{1.1, 2, 5, 55, 66.6, 99.9}));
}
public static double max(double...values){
double max = Double.MIN_VALUE;
for(double i: values){
if(i > max){
max = i;
}
}
return max;
}
输出:
99.9
四、枚举类
1.定义枚举类
public static void main(String[] args) {
Week week = Week.Monday;
System.out.println(week);
System.out.println("Week所有值:");
for(Week a: Week.values()) {
System.out.println(a);
}
}
week为例子
enum week{
Monday,Tuesday,Wednesday,Thusday,Friday,Saturday,Sunday;
}
2.添加构造器
enum Week{
Monday("星期一"),Tuesday("星期二"),Wednesday("星期三"),Thusday("星期四"),Friday("星期五"),Saturday("星期六"),Sunday("星期日");
String name;
Week(String name){
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
运行代码与结果:
//代码
public static void main(String[] args) {
System.out.println("Week所有值:");
for(Week a: Week.values()) {
//自动调用枚举类内部重写的toString()
System.out.println(a);
}
}
//结果
Week所有值:
星期一
星期二
星期三
星期四
星期五
星期六
星期日
五、反射
反射就是将一个类内部构造获取出来,包括private,反射知识在学习使用框架的时候有大用
1.Class类
在程序运行期间,Java运行时系统始终为所有对象维护一个运行时类型标识。这个信息会跟踪每个对象所属的类。虚拟机利用运行时类型信息选择要执行的正确方法。
使用Class类来保存这些类的信息,通过Class类内部方法来进行调用获取设置操作
public class ClassDemo {
public static void main(String[] args) {
Person p = new Person(36 , "张三");
Class c = p.getClass();
}
}
class Person {
public int age;
public String name;
private double selery;
public Person(int age , String name,double selery) {
this.age = age;
this.name = name;
this.selery = selery;
}
public Person(){
}
private Person(int age){
this.age = age;
this.name = "无名";
this.selery = Integer.MAX_VALUE;
}
public static void print(){
System.out.println("人类");
}
public int getAge(){
return this.age;
}
private double getSelery(){
return this.selery;
}
}
2.Class类应用
1)反射方法
反射类内部方法(包括private)
getDeclaredMethods() 获取方法的数组,并返回
getDeclaredMethod(String methodName) 获取内部指定方法
public static void main(String[] args) {
Person p = new Person(36 , "张三" , 3.6);
Class c = p.getClass();
Method[] methods = c.getDeclaredMethods();
for(Method m: methods){
String name = m.getName();
Class returnType = m.getReturnType();
System.out.println("名字是:"+name + "的类的返回类型为:" + returnType);
}
}
class Person {
public int age;
public String name;
private double selery;
public Person(int age , String name,double selery) {
this.age = age;
this.name = name;
this.selery = selery;
}
public static void print(){
System.out.println("人类");
}
public int getAge(){
return this.age;
}
private double getSelery(){
return this.selery;
}
}
//结果
名字是:print的类的返回类型为:void
名字是:getAge的类的返回类型为:int
名字是:getSelery的类的返回类型为:double
2)反射字段
用到Modifer类来检测字段是否私有,私有着f 设置访问权限,然后再进行访问
getDeclaredFields() 为获取字段,并构成数组返回
getDeclaredField(String fileName) 获取单个字段
setAccessible(boolean) 设置权限
public static void main(String[] args) {
Person p = new Person(36 , "张三" , 3.6);
Class c = p.getClass();
Field[] fields = c.getDeclaredFields();
for(Field f: fields){
String name = f.getName();
Object obj = null;
try {
//假如是私有字段
if(Modifier.isPrivate(f.getModifiers())){
//将其访问权限设置为true
f.setAccessible(true);
}
obj = f.get(p);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("字段的名字是:"+name+"\t值是:" + obj);
}
}
3)反射构造器
getConstructors() 获取构造器数组
public static void main(String[] args) {
Person p = new Person(36 , "张三" , 3.6);
Class c = p.getClass();
Constructor[] constructors = c.getConstructors();
for(Constructor constructor : constructors){
System.out.println(constructor.getName());
}
}
//结果
包名.Person
包名.Person
4)反射补充内容
运行代码
public static void main(String[] args) {
Person p = new Person(36 , "张三" , 3.6);
Person q = new Person(26 , "李四" , 3.6);
System.out.println(p.getClass() == p.getClass());
}
运行结果
true
特别说明,getClass() 得到的都是编译之后的class文件,每个类只有一个class文件,所以返回的是true,这是区别于对象概念的,每个对象都是依照class文件为模板构造出来的,对象虽然不同,但是class文件是同一个