打怪升级之小白的大数据之旅(十七)<Java面向对象进阶之常用其他核心类>

打怪升级之小白的大数据之旅(十七)

Java面向对象进阶之常用其他核心类

上次回顾

上次着重对String这个类进行了介绍,本章对一些我们日常会用到的其他核心类进行分享,本章节要介绍的核心类有:数学&日期&系统工具类&数组工具类&包装类&枚举;别怕类太多记不住,需要大概有个印象,当需要使用的时候,随时翻阅笔记或者问问万能的度娘即可~~

数学相关类

Math

java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。

  • 返回圆周率:Math.PI

        double pi = Math.PI;
    
  • 返回 double 值的绝对值:Math.abs(double a)

        double d1 = Math.abs(-5); //d1的值为5
        double d2 = Math.abs(5); //d2的值为5
    
  • 返回大于等于参数的最小的整数:Math.ceil(double a)

        double d1 = Math.ceil(3.3); //d1的值为 4.0
        double d2 = Math.ceil(-3.3); //d2的值为 -3.0
        double d3 = Math.ceil(5.1); //d3的值为 6.0
    
  • 返回小于等于参数最大的整数:Math.floor(double a)

        double d1 = Math.floor(3.3); //d1的值为3.0
        double d2 = Math.floor(-3.3); //d2的值为-4.0
        double d3 = Math.floor(5.1); //d3的值为 5.0
    
  • 返回最接近参数的 long。(相当于四舍五入方法) :Math.round(double a)

        long d1 = Math.round(5.5); //d1的值为6.0
        long d2 = Math.round(5.4); //d2的值为5.0
    
  • 返回a的b幂次方法: Math. pow(double a,double b)

        double result = Math.pow(2,31);
    
  • 返回a的平方根:Math.sqrt(double a)

      double sqrt = Math.sqrt(double a);
    
  • 返回[0,1)的随机值: Math.random()

        double rand = Math.random();
    
  • 返回x,y中的最大值:Math.max(double x, double y)

    double x = 1.1;
    double y = 2.1;
    double result = Math.max(x,y);
    
  • 返回x,y中的最小值:Math.min(double x, double y)

    double x = 1.1;
    double y = 2.1;
    double result = Math.min(x,y);
    
  • Math方法练习:

    // 请使用Math 相关的API,计算在 -10.8  到5.9  之间,绝对值大于6  或者小于2.1 的整数有多少个?
    public class MathTest {
      public static void main(String[] args) {
        // 定义最小值
        double min = -10.8;
        // 定义最大值
        double max = 5.9;
        // 定义变量计数
        int count = 0;
        // 范围内循环
        for (double i = Math.ceil(min); i <= max; i++) {
          // 获取绝对值并判断
          if (Math.abs(i) > 6 || Math.abs(i) < 2.1) {
            // 计数
            count++;
          }
        }
        System.out.println("个数为: " + count + " 个");
      }
    }
    

Random

用于产生随机数:java.util.Random

  • public Random():创建一个新的随机数生成器。此构造方法将随机数生成器的种子设置为某个值,该值与此构造方法的所有其他调用所用的值完全不同。(没有真正的随机数,需要种子产生随机数,同一个种子产生的伪随机数序列相同)

  • public Random(long seed):使用单个 long 种子创建一个新的随机数生成器。该种子是伪随机数生成器的内部状态的初始值,该生成器可通过方法 next(int) 维护。

  • boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 boolean 值。

  • void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。

  • double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 double 值。

  • float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 float 值。

  • double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0。

  • int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。

  • int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。

  • long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。

示例代码:

@Test
	public void test03(){
		Random r = new Random();
		System.out.println("随机整数:" + r.nextInt());
		System.out.println("随机小数:" + r.nextDouble());
		System.out.println("随机布尔值:" + r.nextBoolean());
	}

BigInteger

不可变的任意精度的整数,就跟它的名字一样,它用来对很大的整数进行操作,内部是使用字符串进行存储的

常用方法:

  • BigInteger(String val)
  • BigInteger add(BigInteger val)
  • BigInteger subtract(BigInteger val)
  • BigInteger multiply(BigInteger val)
  • BigInteger divide(BigInteger val)
  • BigInteger remainder(BigInteger val)
  • int intValue():将此 BigInteger 转换为 int。
  • long longValue():将此 BigInteger 转换为 long。
  • float floatValue():将此 BigInteger 转换为 float。

示例代码:

@Test
	public void test01(){
//		long bigNum = 123456789123456789123456789L;
		
		BigInteger b1 = new BigInteger("123456789123456789123456789");
		BigInteger b2 = new BigInteger("78923456789123456789123456789");
		
//		System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和
		
		System.out.println("和:" + b1.add(b2));
		System.out.println("减:" + b1.subtract(b2));
		System.out.println("乘:" + b1.multiply(b2));
		System.out.println("除:" + b2.divide(b1));
		System.out.println("余:" + b2.remainder(b1));
	}

BigDecimal

不可变的、任意精度的有符号十进制数。

常用方法

  • BigDecimal(String val)
  • BigDecimal add(BigDecimal val)
  • BigDecimal subtract(BigDecimal val)
  • BigDecimal multiply(BigDecimal val)
  • BigDecimal divide(BigDecimal val)
  • BigDecimal divide(BigDecimal divisor, int roundingMode)
  • BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
  • BigDecimal remainder(BigDecimal val)
  • double doubleValue():将此 BigDecimal 转换为 double。

  • 示例代码:
@Test
	public void test02(){
		/*double big = 12.123456789123456789123456789;
		System.out.println("big = " + big);*/
		
		BigDecimal b1 = new BigDecimal("123.45678912345678912345678912345678");
		BigDecimal b2 = new BigDecimal("7.8923456789123456789123456789998898888");
		
//		System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和
		
		System.out.println("和:" + b1.add(b2));
		System.out.println("减:" + b1.subtract(b2));
		System.out.println("乘:" + b1.multiply(b2));
		System.out.println("除:" + b1.divide(b2,20,RoundingMode.UP));//divide(BigDecimal divisor, int scale, int roundingMode)
		System.out.println("除:" + b1.divide(b2,20,RoundingMode.DOWN));//divide(BigDecimal divisor, int scale, int roundingMode)
		System.out.println("余:" + b1.remainder(b2));
	}
	//保留两位小数的方式:
	@Test
	public void test02(){
        double f = 111231.5585;
		BigDecimal bg = new BigDecimal(f);
		double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		System.out.println(f1);
    }

日期时间API

  • 时间日期也是我们经常会遇到的的操作,因此,java专门有一个日期时间的API供我们使用,目前主要分为两大类,一类是jdk8之前的Date和Calendar类,一类是LocalDate相关的类
  • 因为Date类有很多漏洞存在,因此在jdk8之后,java创建了一个新的操作日期的API,我推荐使用后面的那个,但因为在公司中,很多程序员还是使用jdk8以前的日期操作,所以还是需要了解一下的

jdk8之前的日期API

Date:java.util.Date

语法格式:

new  Date():当前系统时间
long  getTime():返回该日期时间对象距离1970-1-1 0.0.0 0毫秒之间的毫秒值
new Date(long 毫秒):把该毫秒值换算成日期时间对象

示例代码:

@Test
	public void test5(){
		long time = Long.MAX_VALUE;
		Date d = new Date(time);
		System.out.println(d);
	}
	
	@Test
	public void test4(){
		long time = 1559807047979L;
		Date d = new Date(time);
		System.out.println(d);
	}
	@Test
	public void test3(){
		Date d = new Date();
		long time = d.getTime();
		System.out.println(time);//1559807047979
	}
	
	@Test
	public void test2(){
		long time = System.currentTimeMillis();
		System.out.println(time);//1559806982971
		//当前系统时间距离1970-1-1 0:0:0 0毫秒的时间差,毫秒为单位
	}
	
	@Test
	public void test1(){
		Date d = new Date();
		System.out.println(d);
	}
Calendar:java.util.Calendar
  • Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。与其他语言环境敏感类一样,Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象

  • 语法格式:
    (1)getInstance():得到Calendar的对象

    (2)get(常量)

  • 示例代码

    @Test
    	public void test6(){
    		Calendar c = Calendar.getInstance();
    		System.out.println(c);
    		
    		int year = c.get(Calendar.YEAR);
    		System.out.println(year);
    		
    		int month = c.get(Calendar.MONTH)+1;
    		System.out.println(month);
    		
    		//...
    	}
    
    	@Test
    	public void test7(){
    		TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
    		
    		//getInstance(TimeZone zone)
    		Calendar c = Calendar.getInstance(t);
    		System.out.println(c);
    	}
    
SimpleDateFormat

SimpleDateFormat用于日期时间的格式化

  • 在实际工作中,日期时间肯定不能是Data默认的日期格式,我们需要根据需求,对日期的格式进行处理,因此,就会使用SimpleDateFormat类在这里插入图片描述

  • 示例代码:

    @Test
    	public void test10() throws ParseException{
    		String str = "2019年06月06日 16时03分14秒 545毫秒  星期四 +0800";
    		SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒  E Z");
    		Date d = sf.parse(str);
    		System.out.println(d);
    	}
    	
    	@Test
    	public void test9(){
    		Date d = new Date();
    
    		SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒  E Z");
    		//把Date日期转成字符串,按照指定的格式转
    		String str = sf.format(d);
    		System.out.println(str);
    	}
    

jdk8之后的日期API

jdk8之前的日期格式缺陷:

  • Java1.0中包含了一个Date类,但是它的大多数方法已经在Java 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是
    • 可变性:象日期和时间这样的类对象应该是不可变的。Calendar类中可以使用三种方法更改日历字段:set()、add() 和 roll()。
    • 偏移性:Date中的年份是从1900开始的,而月份都是从0开始的。
    • 格式化:格式化只对Date有用,Calendar则不行。
    • 此外,它们也不是线程安全的等。
  • java8 吸收了第三方开发日期(Joda-Time) 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于时钟(Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类
LocalDate/LocalTime/LocalDateTime

常用方法:

方法描述
now() / now(ZoneId zone)静态方法,根据当前时间创建对象/指定时区的对象
of()静态方法,根据指定日期/时间创建对象
getDayOfMonth()/getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366)
getDayOfWeek()获得星期几(返回一个 DayOfWeek 枚举值)
getMonth()获得月份, 返回一个 Month 枚举值
getMonthValue() / getYear()获得月份(1-12) /获得年份
getHours()/getMinute()/getSecond()获得当前对象对应的小时、分钟、秒
withDayOfMonth()/withDayOfYear()/withMonth()/withYear()将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象
with(TemporalAdjuster t)将当前日期时间设置为校对器指定的日期时间
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()向当前对象添加几天、几周、几个月、几年、几小时
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours()从当前对象减去几月、几周、几天、几年、几小时
plus(TemporalAmount t)/minus(TemporalAmount t)添加或减少一个 Duration 或 Period
isBefore()/isAfter()比较两个 LocalDate
isLeapYear()判断是否是闰年(在LocalDate类中声明)
format(DateTimeFormatter t)格式化本地日期、时间,返回一个字符串
parse(Charsequence text)将指定格式的字符串解析为日期、时间

示例代码:

@Test
	public void test7(){
		LocalDate now = LocalDate.now();
		LocalDate before = now.minusDays(100);
		System.out.println(before);//2019-02-26
	}
	
	@Test
	public void test06(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		LocalDate go = lai.plusDays(160);
		System.out.println(go);//2019-10-20
	}
	
	@Test
	public void test05(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		System.out.println(lai.getDayOfYear());
	}
	
	
	@Test
	public void test04(){
		LocalDate lai = LocalDate.of(2019, 5, 13);
		System.out.println(lai);
	}
	
	@Test
	public void test03(){
		LocalDateTime now = LocalDateTime.now();
		System.out.println(now);
	}
	
	@Test
	public void test02(){
		LocalTime now = LocalTime.now();
		System.out.println(now);
	}
	
	@Test
	public void test01(){
		LocalDate now = LocalDate.now();
		System.out.println(now);
	}
ZoneDateTime

代表指定时区的日期时间
语法格式:
ZonedDateTime.now(ZoneId.of("时区ID"));

示例代码:

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class TestZonedDateTime {
	public static void main(String[] args) {
		ZonedDateTime t = ZonedDateTime.now();
		System.out.println(t);
		
		ZonedDateTime t1 = ZonedDateTime.now(ZoneId.of("America/New_York"));
		System.out.println(t1);
	}
}
Period&Duration
  • Period:用于计算两个“日期”间隔,

  • 示例代码:

    	public static void main(String[] args) {
    			LocalDate t1 = LocalDate.now();
    			LocalDate t2 = LocalDate.of(1994, 1, 1);
    			Period between = Period.between(t1, t2);
    			System.out.println(between);
    			
    			System.out.println("相差的年数:"+between.getYears());//可以用于计算年纪
    			System.out.println("相差的月数:"+between.getMonths());//计算除过年份以外,今年经过的月数
    			System.out.println("相差的天数:"+between.getDays());//可以计算相隔的天数
    			System.out.println("相差的总数:"+between.toTotalMonths());//可以计算相隔的月数
    		}
    
  • Duration:用于计算两个“时间”间隔

  • 示例代码:

    public static void main(String[] args) {
    		LocalDate t1 = LocalDate.now();
    		LocalDate t2 = LocalDate.of(2018, 12, 31);
    		Period between = Period.between(t1, t2);
    		System.out.println(between);
    		
    		System.out.println("相差的年数:"+between.getYears());//1年
    		System.out.println("相差的月数:"+between.getMonths());//又7个月
    		System.out.println("相差的天数:"+between.getDays());//零25天
    		System.out.println("相差的总数:"+between.toTotalMonths());//总共19个月
    	}
    
DateTimeFormatter:日期时间格式化

格式化的三种方法:

  • 预定义的标准格式。如:DateTimeFormatter.ISO_DATE_TIME; ISO_DATE

  • 本地化相关的格式。如:DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)

  • 自定义的格式。如:DateTimeFormatter.ofPattern(“yyyy-MM-dd hh:mm:ss”)

示例代码

@Test
	public void test(){
		LocalDateTime now = LocalDateTime.now();
		//预定义的标准格式
		DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;//2019-06-06T16:38:23.756
        //格式化操作
		String str = df.format(now);
		System.out.println(str);
	}

	@Test
	public void test1(){
		LocalDateTime now = LocalDateTime.now();
		//本地化相关的格式
//		DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//2019年6月6日 下午04时40分03秒
		DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//19-6-6 下午4:40
        //格式化操作
		String str = df.format(now);
		System.out.println(str);
	}

	
	@Test
	public void test2(){
		LocalDateTime now = LocalDateTime.now();
		//自定义的格式
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒  SSS毫秒  E 是这一年的D天");
         //格式化操作
		String str = df.format(now);
		System.out.println(str);
	}

	//把字符串解析为日期对象
    public void test3(){
        //自定义的格式
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy.MM.dd");
        //解析操作
        LocalDate parse = LocalDate.parse("2020.12.12", pattern);
        System.out.println(parse);
    }

系统相关类

System:java.lang.System

System是java操作系统的类,后面IO流的时候就会使用它
系统类中很多好用的方法,其中几个如下:

  • static long currentTimeMillis() :返回当前系统时间距离1970-1-1 0:0:0的毫秒值
  • static void exit(int status) :退出当前系统
  • static void gc() :运行垃圾回收器。
  • static String getProperty(String key):获取某个系统属性

示例代码

public class Test{
    public static void main(String[] args){
    	long time = System.currentTimeMillis();
    	System.out.println("现在的系统时间距离1970年1月1日凌晨:" + time + "毫秒");
    	
    	System.exit(0);

    	System.out.println("over");//不会执行
    }
}

Runtime:java.lang.Runtime

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接

常见的几个方法:

  • public static Runtime getRuntime(): 返回与当前 Java 应用程序相关的运行时对象。

  • public long totalMemory():返回 Java 虚拟机中的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境。

  • public long freeMemory():回 Java 虚拟机中的空闲内存量。调用 gc 方法可能导致 freeMemory 返回值的增加。

  • public long maxMemory(): 返回 Java 虚拟机试图使用的最大内存量。

  • Process exec(String command):在单独的进程中执行指定的字符串命令。

数组工具类:java.util.Arrays

java.util.Arrays数组工具类,提供了很多静态方法来对数组进行操作,而且如下每一个方法都有各种重载形式,以下只列出int[]类型的,其他类型的数组类推

  • static int binarySearch(int[] a, int key) :要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数
  • static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组
  • static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组
  • static boolean equals(int[] a, int[] a2) :比较两个数组的长度、元素是否完全相同
  • static void fill(int[] a, int val) :用val填充整个a数组
  • static void fill(int[] a, int fromIndex, int toIndex, int val):将a数组[fromIndex,toIndex)部分填充为val
  • static void sort(int[] a) :将a数组按照从小到大进行排序
  • static void sort(int[] a, int fromIndex, int toIndex) :将a数组的[fromIndex, toIndex)部分按照升序排列
  • static String toString(int[] a) :把a数组的元素,拼接为一个字符串,形式为:[元素1,元素2,元素3。。。]

示例代码:

import java.util.Arrays;
import java.util.Random;

public class Test{
    public static void main(String[] args){
    	int[] arr = new int[5];
        // 打印数组,输出地址值
  		System.out.println(arr); // [I@2ac1fdc4
  		// 数组内容转为字符串
    	System.out.println("arr数组初始状态:"+ Arrays.toString(arr));
    	
    	Arrays.fill(arr, 3);
    	System.out.println("arr数组现在状态:"+ Arrays.toString(arr));
    	
    	Random rand = new Random();
    	for (int i = 0; i < arr.length; i++) {
			arr[i] = rand.nextInt(100);//赋值为100以内的随机整数
		}
    	System.out.println("arr数组现在状态:"+ Arrays.toString(arr));
    	
    	int[] arr2 = Arrays.copyOf(arr, 10);
    	System.out.println("新数组:" + Arrays.toString(arr2));
    	
    	System.out.println("两个数组的比较结果:" + Arrays.equals(arr, arr2));
    	
    	Arrays.sort(arr);
    	System.out.println("arr数组现在状态:"+ Arrays.toString(arr));
    }
}

包装类

概念

  • 还记得java中的数据类型分类吗?一类是基本数据类型,一类是引用数据类型,基本数据类型的使用效率较高但是它缺少引用数据类型那么丰富的API
  • 就如同解决类只能单继承所以创建了接口那样,java也为基本数据类型创建了其对应的的基本数据类型的包装类
  • 包装类就是把基本数据类型包装成对应的引用数据类型

包装类的分类

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

装箱与拆箱

  • 装箱就是将基本数据类型转换为包装类对象,如:
    int a = 10;
    Integer b = a;
    //或者
    Integer a = 10;
    
  • 拆箱就是将包装类对象转换为基本数据类型,如:
 int a = new Integer(10);

注:
java5之后,java就可以自动装箱与拆箱了
只能与自己对应的类型之间实现自动装箱与拆箱

Integer i = 1;
Double d = 1;//错误的,1是int类型

自动拆箱装箱示例:

Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5; //加法运算完成后,再次装箱,把基本数值转成对象。

包装类常用API

  • 基本数据类型和字符串之间的转换
    (1)把基本数据类型转为字符串
    int a = 10;
    //String str = a;//错误的
    //方式一:
    String str = a + "";
    //方式二:
    String str = String.valueOf(a);
    //方式三:
    Integer i=10;
    String str=i.toString();
    
    (2)把字符串转为基本数据类型
    Stringng转换成对应的基本类型 ,除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型,例如:
方法格式格式说明
public static int parseInt(String s)将字符串参数转换为对应的int基本类型。
public static long parseLong(String s)将字符串参数转换为对应的long基本类型
public static double parseDouble(String s)将字符串参数转换为对应的double基本类型或把字符串转为包装类,然后可以自动拆箱为基本数据类型
public static Integer valueOf(String s)将字符串参数转换为对应的Integer包装类,然后可以自动拆箱为int基本类型
public static Long valueOf(String s)将字符串参数转换为对应的Long包装类,然后可以自动拆箱为long基本类型
public static Double valueOf(String s)将字符串参数转换为对应的Double包装类,然后可以自动拆箱为double基本类型

注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException异常。

示例代码:

  int a = Integer.parseInt("整数的字符串");
  double d = Double.parseDouble("小数的字符串");
  boolean b = Boolean.parseBoolean("true或false");
  
  int a = Integer.valueOf("整数的字符串");
  double d = Double.valueOf("小数的字符串");
  boolean b = Boolean.valueOf("true或false");

后面的方法因为比较简单,直接调用就好了,我就偷个懒,不写示例了

  • 数据类型的最大最小值
    Integer.MAX_VALUE和Integer.MIN_VALUE
    Long.MAX_VALUE和Long.MIN_VALUE
    Double.MAX_VALUE和Double.MIN_VALUE
    
  • 字符转大小写
    Character.toUpperCase('x');
    Character.toLowerCase('X');
    
  • 整数转进制
    Integer.toBinaryString(int i) 
    Integer.toHexString(int i)
    Integer.toOctalString(int i)
    

包装类对象的缓存问题

首先我们看下面的示例代码:

Integer i = 1;
Integer j = 1;
System.out.println(i == j);//true

Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false

是不是很奇怪,为什么上面是true,下面的是false?这就要从包装类的缓存对象谈起,请看下面这个表

包装类缓存对象
Byte-128~127
Short-128~127
Integer-128~127
Long-128~127
Float没有
Double没有
Character0~127
Booleantrue和false

包装类在存储数值时,会在方法区中定义一个缓存对象,当包装类的数据在缓存数值范围内时,直接从内存中取出对象,超过范围会创建新的对象

下面我们完善一下前面那个示例代码:

Integer i = 1;
Integer j = 1;
System.out.println(i == j);//true

Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false

Integer i = new Integer(1);//新new的在堆中
Integer j = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(i == j);//false

Integer i = new Integer(1);//新new的在堆中
Integer j = new Integer(1);//另一个新new的在堆中
System.out.println(i == j);//false

@Test
	public void test3(){
		Double d1 = 1.0;
		Double d2 = 1.0;
		System.out.println(d1==d2);//false 比较地址,没有缓存对象,每一个都是新new的
	}

包装类的类型转换问题

类型转换问题上面提到过了,下面我举个栗子,加深一下印象

@Test
	public void test4(){
		Double d1 = 1.0;
		double d2 = 1.0;
		System.out.println(d1==d2);//true 和基本数据类型比较会自动拆箱,比较数据值
	}
	
	@Test
	public void test2(){
		Integer i = 1000;
		double j = 1000;
		System.out.println(i==j);//true  会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
	}
	
	@Test
	public void test(){
		Integer i = 1000;
		int j = 1000;
		System.out.println(i==j);//true 会自动拆箱,按照基本数据类型进行比较
	}

包装类的不可变对象问题

public class TestExam {
	public static void main(String[] args) {
		int i = 1;
		Integer j = new Integer(2);
		Circle c = new Circle();
		change(i,j,c);
		System.out.println("i = " + i);//1
		System.out.println("j = " + j);//2
		System.out.println("c.radius = " + c.radius);//10.0
	}
	
	/*
	 * 方法的参数传递机制:
	 * (1)基本数据类型:形参的修改完全不影响实参
	 * (2)引用数据类型:通过形参修改对象的属性值,会影响实参的属性值
	 * 这类Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了
	 */
	public static void change(int a ,Integer b,Circle c ){
		a += 10;
//		b += 10;//等价于  b = new Integer(b+10);
		c.radius += 10;
		/*c = new Circle();
		c.radius+=10;*/
	}
}
class Circle{
	double radius;
}

这里有一个小坑,很多人觉得,既然包装类是引用数据类型,那么被当做参数传递时,方法内部改变了值,对应的引用对象的值也会改变,其实在源码中会发现(以Integer举例)
在这里插入图片描述
源码内部,声明了它是一个不可变的值,我们就把包装类当做就如同String类一样特殊处理就好啦,

枚举

概念

  • 介绍枚举之前,举个实际的案例:
    当我们在日常生活中,手机是必不可少的工具吧,而手机中的微信和支付宝则是最主要的支付手段,当我们在购买某个商品时,通常会有几个选项:微信支付、支付宝、银行卡等等
  • 这些支付手段不能是使用 if 进行判断的吧,那样效率太低而且不易于维护,因此,枚举就是为了解决这个问题而诞生
  • 枚举类型本质上也是一种类,只不过是这个类的对象是固定的几个,而不能随意让用户创建。
  • 在JDK1.5之前,需要程序员自己通过特殊的方式来定义枚举类型。
  • 在JDK1.5之后,Java支持enum关键字来快速的定义枚举类型。

枚举类的创建

为了便于理解枚举类的理解,我会使用时间节点演示枚举类的创建

  • JDK1.5之前声明枚举类,以创建四季类举例

    • 步骤一: 构造器加private私有化
    • 步骤二: 本类内部创建一组常量对象,并添加static修饰符,对外暴露这些常量对象
    • 示例代码:
      public class TestEnum {
      	public static void main(String[] args) {
      		Season spring = Season.SPRING;
      		System.out.println(spring);
      	}
      }
      class Season{
          private String seasonName;
      
          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("冬");
      
          private Season(String name){
              this.seasonName=name;
          }
      
          @Override
          public String toString() {
              return seasonName;
          }
      }
      
  • JDK1.5之后的枚举

    • 定义格式:
      【修饰符】 enum 枚举类名{
          常量对象列表
      }
      
      【修饰符】 enum 枚举类名{
          常量对象列表;
          
          其他成员列表;
      }
      
    • 示例代码:
      public class TestEnum {
      	public static void main(String[] args) {
      		Season spring = Season.SPRING;
      		System.out.println(spring);
      	}
      }
      enum Season{
      	SPRING,SUMMER,AUTUMN,WINTER
      }
      

枚举类的要求和特点

  • 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
  • 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
  • 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数,
  • 如果枚举类需要的是有参构造,需要手动定义private的有参构造,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。
  • 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
  • JDK1.5之后switch,提供支持枚举类型,case后面可以写枚举常量名。
  • 枚举类型如有其它属性,建议(不是必须)这些属性也声明为final的,因为常量对象在逻辑意义上应该不可变。

枚举类的常用方法

方法格式使用说明
toString()默认返回的是常量名(对象名),可以继续手动重写该方法!
name()返回的是常量名(对象名) 【很少使用】
ordinal()返回常量的次序号,默认从0开始
values()返回该枚举类的所有的常量对象,返回类型是当前枚举的数组类型,是一个静态方法
valueOf(String name)根据枚举常量对象名称获取枚举对象

示例代码:

public class TestEnum {
	public static void main(String[] args) {
		Season[] values = Season.values();
		for (int i = 0; i < values.length; i++) {
			switch(values[i]){
			case SPRING:
				System.out.println(values[i]+":春暖花开,万物复苏");
				break;
			case SUMMER:
				System.out.println(values[i]+":百花争艳,郁郁葱葱");
				break;
			case AUTUMN:
				System.out.println(values[i]+":菊桂飘香,百树凋零");
				break;
			case WINTER:
				System.out.println(values[i]+":梅花独开,大地一色");
				break;
			}
		}
	}
}
enum Season{
	SPRING,SUMMER,AUTUMN,WINTER
}

做个练习加深一下对枚举的使用吧:
1、声明月份枚举类Month:

1)创建:1-12月常量对象

    JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER

(2)声明两个属性:value(月份值,例如:JANUARY的value为1),
					 description(描述,例如:JANUARY的description为1月份是一年的开始)。

(3)声明一个有参构造,创建12个对象

(4)声明一个方法:public static Month getByValue(int value)5)手动重写toString():返回对象信息,例如:1->JANUARY->1月份是一年的开始。

2、在测试类中,从键盘输入11-12的月份值,获取对应的月份对象,并打印对象

答案:

package com.test01enum;
/*1、声明月份枚举类Month:
(1)创建:1-12月常量对象
    JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER
(2)声明两个属性:value(月份值,例如:JANUARY的value为1),
					 description(描述,例如:JANUARY的description为1月份是一年的开始)。
(3)声明一个有参构造,创建12个对象
(4)声明一个方法:public static Month getByValue(int value)
(5)手动重写toString():返回对象信息,例如:1->JANUARY->1月份是一年的开始。
2、在测试类中,从键盘输入1个1-12的月份值,获取对应的月份对象,并打印对象
*
* */
import java.util.Scanner;
// 测试类
public class Demo {
    // 主方法入口
    public static void main(String[] args) {
        // 创建扫描器
        Scanner sc = new Scanner(System.in);
        // 实例化枚举对象
        System.out.println("请输入月份: 示例:1");
        Month mon = Month.getByValue(sc.nextInt());
        System.out.println(mon);
    }
}


// 创建枚举类
enum Month{
    // 创建月份的常量对象
    JANUARY(1,"一月"),
    FEBRUARY(2,"二月"),
    MARCH(3,"三月"),
    APRIL(4,"四月"),
    MAY(5,"五月"),
    JUNE(6,"六月"),
    JULY(7,"七月"),
    AUGUST(8,"八月"),
    SEPTEMBER(9,"九月"),
    OCTOBER(10,"十月"),
    NOVEMBER(11,"十一月"),
    DECEMBER(12,"十二月");

    // 定义属性 value(月份值,例如JANUARY的value值为1) description为描述信息
    private int value;
    private String description;

    // 定义有参构造器
    Month(int value,String description){
        this.value = value;
        this.description = description;
    }

    // 创建一个方法
    public static Month getByValue(int value){
        // 获取所有常量对象,并根据value返回对应的常量对象,因为起始下标从1开始,因此需要将偏移量定为value-1
        Month[] monthList =  Month.values();
        return monthList[value-1];
    }

    // 重写toString方法,返回对象信息 例如: 1->JANUARY->1月份是一年的开始。

    @Override
    public String toString() {
        return value + "->" + getByValue(value).name() + "->" + description;
    }
}

注: toString的方法中,如果只是调用getByValue这个方法,会造成死递归哦,因为它返回的是一个对象,所以我们需要再调用枚举的.name()方法,获取这个对象名称即可

总结

  • 本章对其他的常用核心类数学、日期、系统工具、数组工具类以及枚举类进行分享,除枚举和包装类之外其他类大致了解一下用法,需要的时候随时查看文档或问度娘
  • 包装类需要记住它的内存传参机制,防止以后使用时因小失大,枚举多写几遍就记住啦
  • 好了,下一期,我会介绍集合,集合是个重点哈,前面介绍的哈希也会在这一章介绍。。如果对我分享的博客格式、代码示例、整体流程框架有什么好的建议,欢迎大家后台吐槽~我会第一时间进行改进
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值