目录
数字
内置类型可以直接使用定义变量,包装期类型相当于对象类型;c语言或perl语言没有制定数值类型的大小和精度,跟平台有关系,与他们不同,java为了实现可移植性,明确定义了数值类型的大小和精度,
其实boolean也算上(boolean变量编译后被转换为int变量,占用4个字节的存储空间,true被转换为1赋值给int变量,false被转换为0赋值给int变量。因此,程序需要判断数值的真或假时,即可以用boolean类型变量,也可以用int类型的变量,当然也可以用byte类型的变量)
类型列表:
内置类型 | 对象包装器 | 大小-字节 | 内置大小-位 | 解释 |
byte | Byte | 1 | 8 | 有符号整形 |
short | Short | 2 | 16 | 有符号整形 |
int | Integer | 4 | 32 | 有符号整形 |
long | Long | 8 | 64 | 有符号整形 |
float | Float | 4 | 32 | 浮点数 |
double | Double | 8 | 64 | 浮点数 |
char | Character | 2 | 16 | 无符号Unicode字符 |
n/a | BigInteger | unlimited | unlimited | 任意大小的不可变整数值 |
n/a | BigDecimal | unlimited | unlimited | 任意大小和精度的不可变浮点数值 |
需要注意的是,上面的char,专门用于表示和操作unicode字符的数据类型。
包装器的作用就是将一个数字构成的字符串转换为数值类型
基本类型的数字一个常遇到的问题是,有时候需要将基本类型的数字传递给一个方法,但是方法需要一个Object参数,此时可以使用自动装箱和自动拆箱实现
java.lang.Math类将整个”数学库“集成在一个类中,包括求平方根,最小最大值,取整,三角函数,随机数发生器等,比如随机数
字符型和字符串型
字符型
字符型通常用于表示单个字符,字符型值必须使用单引号(‘)括起来。Java语言使用16位的Unicode字符集作为编码方式,而Unicode被设计成支持世界上所有书面语言的字符,因此Java程序支持各种语言的字符
字符型值有三种表示形式:
- 直接通过单个字符来指定字符型值,如’A‘,’2‘等
- 通过转义字符表示特殊字符型值,如’\n‘,'\t'等
- 直接用Unicode值表示字符型值,格式’\uXXXX‘,其中XXXX代表一个十六进制的整数
常用的转义字符:
转义字符 | unicode表示 | 解释 |
\b | \u0008 | 退格符 |
\n | \u000a | 换行符 |
\r | \u000d | 回车符 |
\t | \u0009 | 制表符 |
\" | \u0022 | 双引号 |
\' | \u0027 | 单引号 |
\\ | \u005c | 反斜线 |
字符型值也可以使用十六进制编码方式来表示,范围是’\u0000‘~'\uFFFF' ,一共可以表示65536个字符,其中前256个’\u0000‘~'\u00FF'字符和ASCII吗中的字符重合;计算机在底层保存字符时,实际是保存该字符对应的编号,所以char类型的值也可以直接作为整形值使用,相当于一个十六位的无符号整数,范围为0~65536,当然也可以进行加减乘除等数学运算,比较大小;如果吧一个0~65536范围内的整形值赋给char类型变量,系统会自动吧这个int整形当成char类型来处理
范例:
public class test {
public static void main(String[] args){
// 定义一个单个字符的字符变量
char achar='中';
System.out.println(achar);
//定义一个转义字符值
char enterchar='\r';
System.out.println(enterchar);
//使用Unicode编码值来定义字符值
char bchar='\u9999';
System.out.println(bchar);
//使用achar中文字符值来定义整形值
int c_i=achar;
System.out.println(c_i);
//使用整形值来定义字符值
char char1=97;
System.out.println(char1);
}
}
Java没有提供字符串的基本数据类型,但是提供了String类来表示字符串,下面将介绍。
Java语言中的单引号,双引号,反斜线都有特殊用途,如果一个字符串中包含了这些特殊字符,则应该使用转义字符的表示形式,比如使用一个绝对路径“c:\javacode”中表示是不对的,因为Java会把反斜线当成转义字符,所以应该写为"c:\\javacode"
字符串
字符串一连串的字符序列,Java没有提供字符串的基本数据类型,Java的字符串用String来表示,他是一个预定义的类型(类),也就是一个对象,当然有他自己的方法。
给定一个字符串对象构造了实例后不能改变,比如String str1=“Hello” + “gel”,变量str1所引用的特定内容就不可以改变,直到这个对象被销毁;当然你可以让变量引用另一个字符串,甚至可以引用一个从原来字串中派生出来的子串,例如str1=str1.trim().即便是toUpperCase()这样的方法也不能改变字符串对象,只能返回一个新的字符串对象,包含转换后的字符串。
String是Java的 一个基本(类)型,与核心API中大多数其他类不同,字符串行为不可变,因为他有final标记,不能从他派生 出子类,字符串不变性是Java虚拟机的基本原理之一,特别是涉及到多线程编程或者来自多个组织的软件协同工作。可以安全地将不可变对象传递给第三方库并且期望不可修改。
还有另两个类StringBuffer和StringBuilder,他们都是用来代表字符串对象,可以修改
当一个StringBuffer被创建以后,总过StringBuffer提供的append(),insert(),reverse(),setCharAt(),setLength()等方法可以改变这个字符串对象的字符序列,一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
JDK1.5增加了一个StringBuilder类,也代表字符串对象,其实他和StringBuffer基本类似,两个类的构造器和方法也基本相同,区别是,StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高,所以有限使用StringBuilder类。
当然c语言的字符串是一个字符数组,比如char*
String 简单用法,既然是对象,就有一些方法可以使用,
使用String substring(int beginIndex)或者String substring(int beginIndex,int endIndex)的方法返回一个新的字串
//String a="Hello world!";
String a=new String("Hello world!");
System.out.println(a);
String b=a.substring(1);
System.out.println(b);
string的char charAt(int index) 获取字符串中制定位置的字符,其中index为下标,从0到length-1;以下是打印字符串中的字符
看另一个例子:
上面程序,有三个字符串直接量,还会生成额外的2个字符串直接量,“Hello ”和“Zhangsan”生成的“Hello Zhangsan”,和“Hello Zhangsan”连接“Lisi”生成的“Hello ZhangsanLisi”
从上面可以看到,由于String是不可变的,将生成很多额外历史变量。使用StringBuffer和StringBuilder可以避免此问题
上面以此为创建一个StringBuilder对象,追加插入字符串,替换删除操作,反转,最后打印
另外String有一个很有用的功能是将字符串分割为数组:
public class StringSplitdemo {
public static void main(String[] args) {
String str = "code1,code2,,code4";
String [] result_split = str.split(",");
System.out.println(result_split.length);
for(String item_str : result_split){
System.out.println(item_str);
}
System.out.println("------------------------------");
String [] result_split2 = str.split("[,]+");
System.out.println(result_split2.length);
for(String item_str : result_split2){
System.out.println(item_str);
}
}
}
总结:
Java中String,StringBuilder和StringBuffer的区别
1、运算速度比较(通常情况下):StringBuilder > StringBuffer > String
String是final类不能被继承且为字符串常量,而StringBuilder和StringBuffer均为字符串变量。String对象一旦创建便不可更改,而后两者是可更改的,它们只能通过构造函数来建立对象,且对象被建立以后将在内存中分配内存空间,并初始保存一个null,通过append方法向StringBuffer和StringBuilder中赋值
2. 线程安全性
StringBuilder(非线程安全)
而StringBuilder的方法没有该关键字修饰,所以不能保证线程安全性。是JDK1.5新增的,该类提供一个与StringBuffer兼容的 API,但不能保证同步,所以在性能上较高。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
StringBuffer(线程安全的)
StringBuffer中大部分方法由synchronized关键字修饰,在必要时可对方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致,所以是线程安全的。类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符
3. 总结
String:适用于少量的字符串操作。
StringBuilder:适用于单线程下在字符串缓冲区进行大量操作。
StringBuffer:适用于多线程下在字符串缓冲区进行大量操作。
时间
Java 8之前,存在Data和Calendar用来处理日期,时间的类,包括创建日期,时间对象,获取系统当前日期,时间等;但是,Data无法实现国际化,并且他对不同属性也使用不统一的偏移量,比如月份小时都是从0开始,但是天从1开始,年是1900年开始。Calendar实现太复杂。自从Java 8引入新的日期时间包,提供了很多有用的功能,比如对日期时间的加减操作,所有对象几乎不可变-线程安全等。
新的API定义了十几个大类,可表示“连续的”和“人性化”的时间,这里的时间基于UNIX时间,表示为一个单调递增的数;UNIX的时间值0表示1970年 1月1日0时0分0秒(UTC),UNIX系统诞生的那一刻,增量的一个单位代表1秒钟,并且这种时间表示格式已被用作大多数操作系统的时间基准。
新的Data/Time API包含在5个包中,其中顶层包含了最常用的API
名称 | 描述 |
java.time | 表示日期,时间,瞬时和期间的公共类 |
java.time.chrono | 非ISO日历系统的API |
java.time.format | 格式化类 |
java.time.temporal | 使用fields,adjusters,units访问日期和时间 |
java.time.zone | 支持时区及规则 |
第一个基本包java.time,包含了十几个类,几个枚举雷和一个通用的异常类,基础类:
类 | 描述 |
Instant | 自1970-01-01以来的一个时间点,以纳秒(nanosecond)为单位 |
Duration | 时长,以纳秒(nanosecond)为单位 |
“人性化”类:
类 | 描述 |
DateTimeFields | 存储域-值对的一个映射 |
DayOfWeek | 星期中的一天(如Tuesday) |
LocalDate | 本地日期(年月日) |
LocalTime | 本地时间(时分秒) |
LocalDateTime | LocalDate和LocalTime组合 |
MonthDay | 月日 |
OffsetTime | 带时区偏移的时间,类似-04:00,不包括日期或时区值 |
OffsetDateTime | 带时区偏移的日期时间,类似-01:00 |
Period | 时间长度的描述,如2月3天 |
ZonedDateTime | 带时区和偏移的日期时间 |
Year | 年 |
YearMonth | 年月 |
下面是格式化日期时间的格式字符:
符号 | 含义 | 显示形式 | 例子 |
G | 公元 | 文本 | AD |
y | 公元年 | 年份 | 2018;18 |
D | 一年中的几天 | 数字 | 100 |
M/L | 月 | 数字/文本 | 7;07;Jul;July;J |
d | 一年中的第几天 | 数字 | 20 |
Q/q | 一年中的第几季度 | 数字/文本 | 3;03;Q3;3rd quarter |
Y | 年 | 年份 | 1999;99 |
w | 一年中的某周 | 数字 | 10 |
W | 一个月中的某一周 | 数字 | 4 |
e/c | 星期中的本地天数 | 数字/文本 | 2:02;Tue;Tuesday;T |
E | 星期中的第几天 | 文本 | Tue;Tuesday;T |
F | 某月中星期几出现的序数 | 数字 | 3 |
a | AM/PM表示 | 文本 | PM |
h | 12小时制的小时(1-12) | 数字 | 12 |
H | 24小时制的小时(0-23) | 数字 | 20 |
k | 12小时制的小时(0-11) | 数字 | 2 |
K | 24小时制的小时(1-24) | 数字 | 24 |
m | 小时内的几分 | 数字 | 30 |
s | 分内的几秒 | 数字 | 50 |
S | 毫秒 | 数字 | 987 |
A | 千分之一(纳)天 | 数字 | 1234 |
n | 纳秒 | 数字 | 987654321 |
N | 十亿分之一(纳)天 | 数字 | 1234000000 |
V | 时区ID值 | 文本 | Z;-08:30 |
z | 时区名 | 文本 | PST |
X | 时区偏移Z | Offset-X | Z;-08;-0830 |
x | 时区偏移 | Offset-x | +0000;-08 |
Z | 时区的GMT偏移 | Offset-Z | +0000;-0800 |
O | 本地时区偏移 | Offset-O | GMT+8;GMT+08:00 |
p | 填充下一个 | 填充符 | 1 |
以下是一些例子:
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Calendar;
public class test {
public static void main(String []args) {
System.out.println("---日期,日历的输出,格式化---");
LocalDate ld = LocalDate.now();
System.out.println(ld);
LocalTime lt = LocalTime.now();
System.out.println(lt);
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");
// 使用格式化对象将一个日期格式化为ISO8681标准,使用斜线代替破折号
System.out.println(df.format(LocalDate.now()));
// 使用 同一个格式化对象将字符串格式化为日期
System.out.println(LocalDate.parse("2019/01/01",df));
// 两个日期的加减
System.out.println("---两个日期的加减---");
LocalDate d1 = LocalDate.of(2000, 01, 01);
LocalDate lnow = LocalDate.now();
Period diff = Period.between(d1, lnow);
System.out.println(diff);
System.out.printf("The 21st century (up to %s) is %s old%n",lnow,diff);
System.out.printf("The 21st century is %d years,%d months and % days old%n",
diff.getYears(),diff.getMonths(),diff.getDays());
// 日期,日历的加减
System.out.println("---日期,日历的加减---");
LocalDate now = LocalDate.now();
Period p=Period.ofDays(365);
LocalDate then=now.plus(p);
System.out.printf("365 days from %s is %s %n",now,then);
// 与传统日期的接口
System.out.println("---与传统日期的接口---");
Date legacyd = new Date();
System.out.println(legacyd);
LocalDateTime ndate = LocalDateTime.ofInstant(legacyd.toInstant(), ZoneId.systemDefault());
System.out.println(ndate);
Calendar c = Calendar.getInstance();
System.out.println(c);
LocalDateTime nc = LocalDateTime.ofInstant(c.toInstant(), ZoneId.systemDefault());
System.out.println(nc);
}
}
结果
---日期,日历的输出,格式化---
2019-04-14
19:27:50.878
2019-04-14T19:27:50.878
2019/04/14
2019-01-01
---两个日期的加减---
P19Y3M13D
The 21st century (up to 2019-04-14) is P19Y3M13D old
The 21st century is 19 years,3 months and 13ays old
---日期,日历的加减---
365 days from 2019-04-14 is 2020-04-13
---与传统日期的接口---
Sun Apr 14 19:27:50 CST 2019
2019-04-14T19:27:50.987
java.util.GregorianCalendar[time=1555241271002,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=3,WEEK_OF_YEAR=16,WEEK_OF_MONTH=3,DAY_OF_MONTH=14,DAY_OF_YEAR=104,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=27,SECOND=51,MILLISECOND=2,ZONE_OFFSET=28800000,DST_OFFSET=0]
2019-04-14T19:27:51.002
从上面的例子可以看到使用了一些公共的方法,因为没有set方法,get方法通常无意义,新增的一些方法:
名称 | 描述 |
at | 与另一个对象组合 |
format | 给定格式化器产生一个格式化字符串) |
from | 工厂方法,将输入参数转化为目标实例 |
get | 从实例中获取一个域 |
is | 检查给定对象的状态 |
minus | 减去一个数后返回结果副本 |
of | 工厂方法,解析输入,创建新方法 |
parse | 工厂方法,解析单个输入字符串,产生目标实例 |
plus | 加上一个数后返回结果副本 |
to | 将该对象转换为另一个类型 |
with | 修改制定域并返回一个副本。替换了set方法 |
日期一些函数:
/**
* 返回指定日期所在年份的第几周
* @param dateStr
* @return
*/
public static int weekOfYear(String dateStr){
// 格式化字符串
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendar = Calendar.getInstance();
// 国内第一天设置
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.setTime(date);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
/**
* 获取当前时间所在周的第一天
* @param date
* @return
*/
public static Date getBeginDayOfWeek(Date date) {
if (date == null) {
return null;
}
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// 因为按照Calendar类获取的周日为一周的第一天,按照中国习惯,所以这里需要特殊处理
int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
if (dayofweek == 1) {
dayofweek += 7;
}
cal.add(Calendar.DATE, 2 - dayofweek);
return cal.getTime();
}
/**
* 根据日期获得所在月天数
*
* @param date
* @return
*/
public static Integer getDaysOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
}
Arrays
Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法;使用时导包:import java.util.Arrays
其中常用的:
1,void Array.sort(Object[] array)
功能:对数组按照升序排序
2,Arrays.sort(Object[] array, int from, int to)
功能:对数组元素指定范围进行排序
3,public static String toString(Object[] array)
功能:返回数组的字符串形式
4,public static <T> List<T> asList(T... a)
将一个数组转为list
举例
public class Demo {
public static void main(String[] args) {
String [] arr_str = {"code4","code2","code3"};
List<String> list1 = Arrays.asList(arr_str);
for(String item : list1){
System.out.println(item);
}
System.out.println("------------------------------");
Arrays.sort(arr_str);
for(String item_str : arr_str){
System.out.println(item_str);
}
}
}