常用类
包装类
在类中查看属性方法的快捷键:Ctrl+F12
java.lang包会默认导入每个Java文件,所以我们不需要导入这个包,直接用包中的类就好了
-
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
-
在Java中,类只能直接继承一个类,但可以间接继承多个类
-
包装类就是八大基本类型对应的类(前六个包装类是直接继承Number类,间接继承object类,后两个是直接继承object类)
-
我们为什么要引入包装类?
- 将基本类型包装成为对应的包装类,就是为了获取某些属性,方法
- 集合(存放数据的)只能存放引用数据类型
我们以integer类作讲解,其他都一样:(类的学习都是使用API帮助文档)
-
integer底层就是一个int类型的数据
-
int类型数据的最大最小值,直接类名调用属性就可以了,例如:
System.out.println(Integer.MAX_VALUE); System.out.println(Integer.MIN_VALUE);
-
integer类中没有无参构造器
有参(字符串)构造只能是可以转换为int类型的字符串
-
自动装箱
int类型转换为integer,例如:
Integer i1=12; //其实内部进行的操作是,Integer i1=Integer.valueOf(12);这步我们要通过反编译工具才可以看到
-
自动拆箱
integer类型转换为int类型,例如:
int a=i1;
-
compareTo方法,就是比较大小,例如:
System.out.println(i1.compareTo(i2));//这个方法的返回值就是一个int类型
-
equals方法,比较是否相等,比较的是数值,例如:
System.out.println(i1.equals(i2)); //等于比较的是地址,就是看是否为同一个值 System.out.println(i1==i2);
-
自动装箱的重点:
Integer i1=12; Integer i2=12; System.out.println(i1==i2);//返回值为true,因为值在-128到127之间就直接在一个数组中取值,所以为true /* 如果不在这个范围内就会创建一个对象,不在那个数组里取值,而是自己创建对象存值,所以这也说明了 自动装箱不一定会创建对象,还有数值超出那个范围才会创建对象 */
-
intValue()方法,将integer转换为int类型
System.out.println(i1.intValue());
-
parseInt()方法,将String类型转换为int类型,字符串要可以转换为int,不然会报异常
int i = Integer.parseInt("12");
-
valueof(int i)/(String s)方法,就是将int类型转换为integer类型/将String类型转换为int类型
String类
从属于java.lang包
-
String类的底层就是一个char类型的数组
-
创建对象时调用构造器就是对底层char类型数组的赋值
String类中有很多构造器,可以通过创建对象调用构造器,例如:
String s1 = new String(); String s2 = new String("abc"); String s3 = new String(new char[]{'1', '2', '3'});
一般都是用对象名去调用方法
String类中的方法:
str1.length(),就是str1的长度,底层就是char类型数组的长度(返回结果为int值)
str1.isEmpty()判断这个对象是否为空(返回结果为布尔值)
str1.charAt(2)得到该数组下标(2)对应元素的值(返回结果就是元素对应的值)
str5.equals(str6)判断两个对象值是否相等(返回值为布尔值),内部先判断是否相等,在判断长度是否相等,在判断值是否相等
-
compareTo()方法
String s4="abc"; String s5="abcdef"; System.out.println(s4.compareTo(s5));//返回4,4是长度差1 //这种情况下返回的就是长度差,因为前三个字符是一样的 String s4="abc"; String s5="defghj"; System.out.println(s4.compareTo(s5));//返回的是ASCII码 //只要前三个字符中有一个不一样,就会返回ASCII码,只有前三个字符串全部一样才会返回长度差
-
indexOf()方法
System.out.println(s5.indexOf('f'));//输出的值为元素对应的下标,是个int值
-
API帮助文档提供的是我们可以使用的方法,像private修饰的方法我们就不能使用,所以API文档也不会提供给我们
-
substring()方法,字符串的截取
String s5="abcdef"; String substring = s5.substring(2); System.out.println(substring);//输出cdef String substring1 = s5.substring(2, 3);//这里只能输出一个字符,因为在Java很多地方都是包头不包尾的 System.out.println(substring1);//输出c
-
concat()方法,就是两个字符串进行拼接
String s4="abc"; String s5="abcdef"; System.out.println(s4.concat(s5));//输出abcabcdef
-
replace()方法,就是将字符串中的一个字符替换为另一个字符
String s4="abc"; System.out.println(s4.replace('a', 'p'));//输出结果为pbc,就是将a字符替换成为p字符
-
有返回值的方法可以先返回一个值,然后sout输出,也可以直接sout输出
-
toUpperCase()方法,将字符串中全部字符转换为大写
String s5="abcdef"; System.out.println(s5.toUpperCase());//输出结果为ABCDEF
-
toLowerCase()方法,将字符串中的全部字符转换为小写
String s5="AAAAAA"; System.out.println(s5.toLowerCase());//输出结果为aaaaaa
-
trim()方法,去掉首尾空格
String s5=" AAAA AA "; System.out.println(s5.trim());//输出结果为AAAA AA
-
toString()方法,谁调用就返回谁
String s5="asdfghj"; System.out.println(s5.toString());//输出结果为asdfghj
-
valueOf()方法,将int类型的值转换为字符串
System.out.println(String.valueOf(12));
String内存+反编译验证
字符串定义的方式:
String s1="abc";
String s2="a"+"b"+"c";
String s3="abc"+"";
//字符串拼接,会进行编译期优化,直接拼成最终你要的字符串
String s4=s1+"";
//变量参与运算,就会在堆中开辟空间,会创建一个StringBuilder对象
String s5=new String("abc");
//创建对象,会在堆中开辟空间
System.out.println(s1==s2);//输出true
System.out.println(s1==s3);//输出true
System.out.println(s1==s4);//输出false
System.out.println(s1==s5);//输出false
编译器优化:自动将s2,s3拼接为"abc",将s4拼接为s1,直接拼成最终你要的字符串
变量的内存地址是由第一个指向的位置决定的(我自己理解出的,不一定对)
-
s1到s5在内存中的存储图大致为:
-
压栈(入栈):对象名,变量名啥的都会被压入栈中,具体怎么压我现在也不知道
StringBuilder类
-
底层最重要的两个数是char类型的数组和int类型的数
-
StringBuilder的无参构造会调用父类的构造器并给char类型数组确定长度为16
你要是调用有参构造器的话会将数组长度确定为你传的那个数字,例如:
StringBuilder stringBuilder = new StringBuilder(23);//开辟长度为23的数组
你要调用字符串有参构造的话,开辟数组长度为字符串长度加默认长度16
StringBuilder stringBuilder1 = new StringBuilder("abc");//开辟长度为19的数组
StringBuilder底层的char数组长度要是不够用了,它会重新创建一个数组,而String是不能重新创建数组
-
String是不可变字符串,StringBuilder是可变字符串
StringBuilder的常用方法
StringBuilder与StringBuffer的区别联系
利用数组扩容原理(StringBuilder类的原理)创建一个类来模拟集合Arraylist:
注意细节:this就是调用本类的构造器,而super是调用父类的构造器
为什么我们要说一个类的底层是一个数组或变量啥的?
因为我们可以发现所有的属性和方法都是给那个数组或变量进行操作,所以我们说这个类的底层就是一个数组或变量啥的
实现代码为:
package 包;
import java.lang.management.MemoryUsage;
public class MyCollection {
//底层是一个object数组
Object[] value;
//计数组中被占用的个数
int size;
//定义无参构造
public MyCollection(){
value=new Object[3];//数组长度赋值为3
}
//定义有参构造,数组长度由参数决定
public MyCollection(int num){
value=new Object[num];
}
//往数组里放东西的方法
public MyCollection add(Object obj){
value[size]=obj;
size++;
//一旦超出范围,我们就要进行数组的扩容
if (size>value.length-1){
//扩容:创建一个新的数组
Object[] newObj=new Object[value.length*2+2];
//将老数组中的东西复制到新数组中
for (int i = 0; i <= value.length-1; i++) {
newObj[i]=value[i];
}
//将value指向newObj,下次就是直接向新数组中放值
value=newObj;
}
return this;
}
//取值
public Object get(int index){
if (index<0||index>=size){
throw new RuntimeException("超出边界");
}
return value[index];
}
//计数组长度
public int size(){
return size;
}
//重写toString方法
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(value[i]+",");
}
sb.setCharAt(sb.length()-1,']');
return sb.toString();
}
public static void main(String[] args) {
MyCollection mc1 = new MyCollection();//调用无参构造创建对象,定义数组长度为3
MyCollection mc2 = new MyCollection(3);//调用有参构造,定义数组长度为3
mc1.add(1);
mc1.add("aaa");
mc1.add(3);
mc1.add(4);//这个数组是能放3个,这是第四个,数组下标越界
mc1.add(5).add(6).add(7);
//输出数组元素
for (int i = 0; i <= mc1.size()-1; i++) {
System.out.println(mc1.get(i));
}
System.out.println(mc1);
System.out.println(mc1.toString());
}
}
时间处理类
-
date类
Date d = new Date(); //打印出当前系统的世间 System.out.println(d);
-
date类中的其他表示时间的方法
Date d = new Date(); //打印出当前系统的时间 System.out.println(d); //以下是过期的打印时间的方法 System.out.println(d.toGMTString()); System.out.println(d.toLocaleString()); System.out.println(d.getYear());//当前年份减去1900 System.out.println(d.getMonth());//返回的是0到11之间的数,5表示6月 System.out.println(d.getDate());//月份中的某一天,值在0到31之间 System.out.println(d.getDay());//返回的是星期几 //以下两个打印的都是毫秒数,但是为什么第二个是常用的呐? System.out.println(d.getTime());//返回的是毫秒数 System.out.println(System.currentTimeMillis());//因为它不用创建对象,不用导包,直接调用 //java.sql.Date 年月日 //java.util.Date 年月日时分秒 java.sql.Date sqlDate=new java.sql.Date(12122121l); System.out.println(sqlDate); //将String类型转换为java.sql.Date java.sql.Date date = sqlDate.valueOf("2019-10-10"); //java.util.Date转换为java.sql.Date(util.Date调用自己的方法充当sql.Date的参数) java.sql.Date date1 = new java.sql.Date(new Date().getTime()); //java.sql.Date转换为java.util.Date(类转类,用的是继承关系,父类子类的关系) Date date2=date1
-
java.sql包下还有两个时间类,Time,Timestamp类,知道有这两个类就行了
-
String转换为java.util.Date
//String----->java.util.Date //1. String----->java.sql.Date java.sql.Date date3 = java.sql.Date.valueOf(2019-1-8); //2. java.sql.Date----->java.util.Date Date date4=date3;
这种方法有局限:valueOf方法中字符串格式必须为:年--月--日
实现开发工作中将String转换为java.util.Date需要借助Dateformat类(日期格式化)
//创建实现类对象时需要确定日期的格式,字符可以是多个也可以是单个,例如:y-M-d h-m-s SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss"); try { //parse方法的作用:String----->Date //这里的日期格式必须和确定的日期格式相同 Date parse = simpleDateFormat.parse("2100-12-10 10-20-30"); System.out.println(parse); } catch (ParseException e) { e.printStackTrace(); } //format方法的作用:Date----->String //这里转换为的String格式为创建对象时确定的日期格式 String format = simpleDateFormat.format(new Date()); System.out.println(format);
字符代表的意思:
-
类创建对象失败的原因:
- 接口
- 抽象类
- 没有无参构造,需要用有参构造创建对象
- 无参构造被private修饰
-
Calendar类(日历)
很强大,但是我们用得少
注意:Calendar类本身(抽象类)不能创建对象,但我们可以让类通过调用方法来创建对象,也可以创建它实现类的对象来创建对象,例如:
Calendar cal1 =Calendar.getInstance(); Calendar cal2 = new GregorianCalendar();
Calendar类中的方法:
//获取方法: System.out.println(cal1.get(Calendar.YEAR));//输出2021 System.out.println(cal1.get(Calendar.MONTH));//输出的月份是当前月份减1 System.out.println(cal1.get(Calendar.DATE));//输出20号 System.out.println(cal1.get(Calendar.DAY_OF_WEEK));//输出的是一个星期中的第几天,例如:星期六是一个星期中 的第七天 System.out.println(cal1.getActualMaximum(Calendar.DATE));//输出这个月中最大的一天 System.out.println(cal1.getActualMaximum(Calendar.MONTH));//输出11,就是12月的意思,因为从0开始 System.out.println(cal1.getActualMinimum(Calendar.DATE));//一个月中最小的一天肯定是1 //设置方法: cal1.set(Calendar.DATE,16);//修改为16号 cal1.set(Calendar.MONTH,9);//修改为9月 cal1.set(Calendar.YEAR,2051);//修改为2051年 System.out.println(cal1);
- String----->Calendar,先转换为date,在转换为Calendar
Calendar cal = Calendar.getInstance(); //String----->Calendar //String----->Date Date date = Date.valueOf("2019-2-10"); //Date----->Calendar cal.setTime(date); System.out.println(cal);
打印输出日历表:
package 包; import java.sql.Date; import java.util.Calendar; import java.util.Scanner; public class Test { public static void main(String[] args) { System.out.print("请输入你想要查看的日期:--(格式例如:2019-10-10):"); Scanner sc=new Scanner(System.in); String str = sc.next();//这个方法使用来接收键盘输入的,接收到数据后要返回一个值 //String----->Calendar 为什么要转为Calendar类型? 答:因为这个类比较强大,只有转化为Calendar类才可以进行后续步骤 Date valueOf = Date.valueOf(str); Calendar cal = Calendar.getInstance(); cal.setTime(valueOf);//转换成功 System.out.println("日\t一\t二\t三\t四\t五\t六"); int count=0; //求出这个月中的最大天数 int actualMaximum = cal.getActualMaximum(Calendar.DATE); //获取当天的天数 int nowDay = cal.get(Calendar.DATE); //修改 cal.set(Calendar.DATE,1); //空格 int num = cal.get(Calendar.DAY_OF_WEEK); for (int i = 1; i <=num-1 ; i++) { System.out.print("\t"); } count+=(num-1); for (int i = 1; i <= actualMaximum; i++) { if (i!=nowDay){ System.out.print(i+"\t"); }else{ System.out.print(i+"*\t"); } count++; if (count%7==0){ System.out.println(); } } } }
枚举
-
用enum关键字来表示
-
枚举的定义
public enum Test { SPRING,SUMMER,AUTUMN,WINTER; }
-
枚举的创建
public void test1(){ //枚举的创建 Test test=Test.SPRING; }
-
枚举的常用方法
//values()方法,将枚举直接变成数组,属性就是元素,类型就是枚举名 public class TestEnum { @Test //加上这个注释就可以直接执行,不需要main方法 public void test(){ Season[] values = Season.values(); for (Season value : values) { System.out.println(value); } } } //ordinal()方法 Season[] values = Season.values(); for (Season value : values) { System.out.println(value.ordinal()); }
-
用枚举来做一个交通信号灯的实例
import org.junit.Test; public class TestEnum { TrafficLight light=TrafficLight.RED; public void test(){ switch (light){ case RED: this.light=TrafficLight.GREEN;break; case GREEN: this.light=TrafficLight.YELLOW;break; case YELLOW: this.light=TrafficLight.RED;break; } } @Test public void test1(){ for (int i = 0; i < 11; i++) { test(); System.out.println(light); } } }
-
枚举的构造方法只能用private修饰
-
只有创建了构造器,枚举的属性后才会有括号
@Test public void test5(){ //创建枚举 枚举属性中的值会直接传到构造器中,可以用构造器来给枚举的属性赋值 Orientation north = Orientation.NORTH; System.out.println(north.getcity()); }
-
EnumMap是一个类(要求所有的键都来自同一个枚举) 是Map的子类
@Test public void test9(){ //EnumMap EnumMap<Orientation,String> map=new EnumMap<>(Orientation.class);//括号中要写键的class //第二个尖括号中的泛型可以不写 map.put(Orientation.NORTH,"beijing"); map.put(Orientation.SOUTH,"nanjing"); map.put(Orientation.WEST,"xizang"); map.put(Orientation.EAST,"shanghai"); //先获取他们所有的键 for (Orientation o:map.keySet()){ System.out.println(o+":"+map.get(o)); } }
Math,Random类
-
Math类从属于java.lang包,无参构造被private修饰
Math类下的一些静态的属性与方法
package 包; import java.sql.Date; import java.util.Calendar; import java.util.Scanner; import static java.lang.Math.*;//静态导入:将Math类中的静态的东西全部导入 public class Test { public static void main(String[] args) { //圆周率 System.out.println(PI); //次幂 System.out.println(pow(3.0,2.0)); //开平方 System.out.println(Math.sqrt(9.0)); //向上取值 System.out.println(Math.ceil(9.1)); //向下取值 System.out.println(Math.floor(9.9)); //四舍五入 System.out.println(Math.round(5.1)); //随机数 范围[0.0,1.0)之间 System.out.println(Math.random()); //绝对值 System.out.println(Math.abs(-9.2)); //取小 System.out.println(Math.min(2.0,9.8)); //取大 System.out.println(Math.max(2.0,9.6)); } //如果本类中有相同的方法,那么优先走本类中的,本类中没有,就去静态导入类中找 public static double sqrt(double d){ return 8.8; } }
-
Random类
//只要你给的数是一个值,它产生的随机数就永远是那些,例如:你传入了5,输出的随机数就只会是那些 //你要想让这些随机数变,就必须一直改变参数 Random r = new Random(5); for (int i = 1; i <= 10; i++) { System.out.println(r.nextInt()); } //可以通过这个方式来改变随机数 Random r = new Random(System.currentTimeMillis()); for (int i = 1; i <= 10; i++) { System.out.println(r.nextInt()); } //也可以通过这样的方式来改变随机数 public static void main(String[] args) { //因为无参构造内部调用的是纳秒,所以无参构造的随机数是一直变的 Random r = new Random(); for (int i = 1; i <= 10; i++) { //还可以是nextDouble/nextBoolean/nextInt System.out.println(r.nextBoolean()); /* 调用nextDouble方法默认随机数范围是0.0到1.0之间,取0.0不取1.0 我们可以在nextInt方法内指定范围,指定数字是多少,范围就是0到多少 例如:指定参数为10,随机数的范围就是0到10,取0不取10 */ } }
要想让随机数一直都是变的:1. 要么是一直改变有参构造的参数(通过调用毫秒等),2. 要么是直接通过无参构造创建对象
学习random类的原因是:Math调用随机数的底层是调用random类的nextDouble方法,所以Math.random的范围是在0.0--1.0之间