这是我学习Java的第三个阶段,在本章中遇到了很多较难理解的东西,同时我也感觉到从这章开始我便不能再单纯的依靠C++的那一点知识来学习,新的东西和难点会越来越多,我也必须投入更多的时间到Java学习中去。
目录
包装类
自动装箱和拆箱
缓存处理
StringBuffer和StringBuilder
IStringBuffer接口
value: 用于存放字符数组capacity: 容量
反转 reverse:
插入insert 和 append
Date时间类(java.util.Date)
DateFormat类的作用
Math类
File类的基本用法
递归打印目录树
枚举
包装类
Java是面向对象的语言,我们经常用到的八种基本数据类型却不是面对对象的。但是我们在实际应用中经常需要将基本数据转化成对象,所以便引入了包装类这个概念。
| 基本数据类型 | 包装类 |
| byte | Byte |
| boolean | Boolean |
| short | Short |
| char | Character |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
Number类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。
void testInteger() { // 基本类型转化成Integer对象 Integer int1 = new Integer(10); Integer int2 = Integer.valueOf(20); // 推荐这种写法 // Integer对象转化成int int a = int1.intValue(); // 字符串转化成Integer对象 Integer int3 = Integer.parseInt("334"); Integer int4 = new Integer("999"); // Integer对象转化成字符串 String str1 = int3.toString(); // 一些常见int类型相关的常量 System.out.println("int能表示的最大整数:" + Integer.MAX_VALUE); }
自动装箱和拆箱
自动装箱:基本类型的数据处于需要对象的环境时,会自动转换为"对象"
Integer a=234; //自动装箱Integer a=Integer.valueOf(234); //调用的是valueOf(100),而不是new Integer(100)int b=a;//编译器会修改成int b=a.intValue();
自动拆箱:每当需要一个值时,对象会自动转换为基本数据类型
Integer i = 100; //自动装箱int j = i; //自动拆箱//编译器会修改成int j = i.intValue();
缓存[-128,127]之间的数,
系统初始的时候,创建了一个缓存数组
当我们调用valueOf()时,首先检查是否在[-128,127]中,若在则直接在缓存数组中取出
若不在则创建新的Integer对象
Integer in1=-12;Integer in2=-12;System.out.println(in1==in2); //trueSystem.out.println(in1.equals(in2)); //trueInteger in3=-123;Integer in4=-123;System.out.println(in3==in4); //false,123不缓存System.out.println(in3.equals(in4)); //true
StringBuffer和StringBuilder
在这里新学了两种用法 : StringBuffer和StringBuilder,应用的场景如下:
1)String:适用于少量字符串操作情况。
2)StringBulider:适用于单线程在字符串缓存区进行大量操作。
3)StringBuffer:适用于多线程在字符串缓存区进行大量操作。”
StringBuffer和StringBuilder非常类似,均代表可变的字符序列。 这两个类都是抽象类AbstractStringBuilder的子类
注意:StrinBuilder线程不安全,但效率高(一般用它)
StringBuffer线程安全,但效率低
用法:
StringBuilder s=new StringBuilder("abc");String.out.println(s); //abcSystem.out.println(Integer.toHexString(sb.hashCode())); //15db9742sb.setCharAt(2,'M'); //替换String.out.println(s); //abMSystem.out.println(Integer.toHexString(sb.hashCode())); //15db9742
可见虽然输出改变了,但其实对象并未改变。
StringBuilder和StringBuffer与String类含义类似的方法
// indexof substring charAtStringBuilder s=new StringBuilder();for(int i=0;i<26;i++){ char temp=(char)('a'+i); //输出26个英文字母 s.append(temp); //abc...xyz}System.out.println(s);sb.reverse(); //倒序 zyxw...cbaSystem.out.println(s);sb.setCharAt(3,'1'); //替换 zyx1...cbaSystem.out.println(s);sb.insert(0,'2'); //插入 2zyx1...cbaSystem.out.println(s); //sb.insert(0,'2').insert(6,'3'); //链式调用thissb.delete(20,23); //删除 也可链式调用System.out.println(s);
StringBuffer是可变长的字符串
String str1 = "let there "; StringBuffer sb = new StringBuffer(str1); //根据str1创建一个StringBuffer对象 sb.append("be light"); //在最后追加 System.out.println(sb); sb.delete(4, 10);//删除4-10之间的字符 System.out.println(sb); sb.insert(4, "there ");//在4这个位置插入 there System.out.println(sb); sb.reverse(); //反转 System.out.println(sb);
为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度,比如说new StringBuffer("the"),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了。
IStringBuffer接口
public interface IStringBuffer { public void append(String str); //追加字符串 public void append(char c); //追加字符 public void insert(int pos,char b); //指定位置插入字符 public void insert(int pos,String b); //指定位置插入字符串 public void delete(int start); //从开始位置删除剩下的 public void delete(int start,int end); //从开始位置删除结束位置-1 public void reverse(); //反转 public int length(); //返回长度
capacity: 容量
无参构造方法: 根据容量初始化value
public MyStringBuffer(){value = new char[capacity];}
有参构造方法:
public MyStringBuffer(String str){ if(null!=str) value =str.toCharArray(); length = value.length; if(capacity
反转 reverse:
public void reverse() { for (int i = 0; i < length / 2; i++) { char temp = value[i]; value[i] = value[length - i - 1]; value[length - i - 1] = temp; } }
插入insert 和 append
边界条件判断:
1.插入之前,首先要判断的是一些边界条件。 比如插入位置是否合法,插入的字符串是否为空扩容
1). 要判断是否需要扩容,如果插入的字符串加上已经存在的内容的总长度超过了容量,那么就需要扩容。
2). 数组的长度是固定的,不能改变的,数组本身不支持扩容。 我们使用变通的方式来解决这个问题。
3). 根据需要插入的字符串的长度和已经存在的内容的长度,计算出一个新的容量。 然后根据这个容量,创建一个新的数组,接着把原来的数组的内容,复制到这个新的数组中来。并且让value这个引用,指向新的数组,从而达到扩容的效果。
2.插入字符串
1. 找到要插入字符串的位置,从这个位置开始,把原数据看成两段,把后半段向后挪动一个距离,这个距离刚好是插入字符串的长度
2. 然后把要插入的数据,插入这个挪出来的,刚刚好的位置里。
3.修改length的值
最后修改length的值,是原来的值加上插入字符串的长度
insert(int, char)
参数是字符的insert方法,通过调用insert(int, String) 也就实现了。
append
追加,就是在最后位置插入。 所以不需要单独开发方法,直接调用insert方法,就能达到最后位置插入的效果
public void insert(int pos, String b) { //边界条件判断 if(pos<0) return; if(pos>length) return; if(null==b) return; //扩容 while(length+b.length()>capacity){ capacity = (int) ((length+b.length())*1.5f); char[] newValue = new char[capacity]; System.arraycopy(value, 0, newValue, 0, length); value = newValue; } char[] cs = b.toCharArray(); //先把已经存在的数据往后移 System.arraycopy(value, pos, value,pos+ cs.length, length-pos); //把要插入的数据插入到指定位置 System.arraycopy(cs, 0, value, pos, cs.length); length = length+cs.length; }
删除 delete
public void delete(int start, int end) { //边界条件判断 if(start<0) return; if(start>length) return; if(end<0) return; if(end>length) return; if(start>=end) return; System.arraycopy(value, end, value, start, length- end); length-=end-start; }
陷阱:
String str8=" ";for(int i=0;i<5000;i++){ str8=str8+i; //相当于产生了10000个对象} //服务器容易崩
替换上式
StringBuilder sb1=new StringBuilder(" ");for(int i=0;i<5000;i++){ sb1.append(i); //不会产生额外的对象,} //直接往sb1后添加//遇到累计字符串时一定要使用StringBuilder
Date时间类(java.util.Date)
long now = System.currentTimeMillis();//获得当前时间
在标准Java类库中包含一个Date类。它的对象表示一个特定的瞬间,精确到毫秒。
1. Date() 分配一个Date对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒)。
2. Date(long date) 分配 Date 对象并初始化此对象,
3. boolean after(Date when) 测试此日期是否在指定日期之后。
4. booleanbefore(Date when) 测试此日期是否在指定日期之前。
5. boolean equals(Object obj) 比较两个日期的相等性。
6. long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
7. String toString() 把此 Date 对象转换为以下形式的 String:
dow mon dd hh:mm:ss zzz yyyy
DateFormat类的作用
把时间对象按照"格式字符串指定的格式"转成相应的字符串。
import java.text.DateFormat;DateFormat df=new SimpleDateFormat("yy-MM-dd hh:mm:ss");//SimpleDateFormat是DateFormat的子类String str =df.format(new Date(4000));System.out.println(str); //1970-01-01 09:06:40
把字符串按照"格式字符串指定的格式"转成相应的时间对象。
public static void main (String[] args)throws ParseException{DateFormat df2=new SimpleDateFormat("yy-MM-dd hh:mm:ss");Date date =df2.parse("1983年5月10日 10时45分59秒");System.out.println(date); //Tue May 10 10:45:59 CST 1983
GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。
//import java.util.*; import java.util.Calendar;import java.util.GregorianCalendar; Calendar calendar = new GregorianCalendar(2999, 10, 9, 22, 10, 50); int year = calendar.get(Calendar.YEAR); // 打印:1999 int month = calendar.get(Calendar.MONTH); // 打印:10 int day = calendar.get(Calendar.DAY_OF_MONTH); // 打印:9 int day2 = calendar.get(Calendar.DATE); // 打印:9 int weekday = calendar.get(Calendar.DAY_OF_WEEK);// 打印:3// 星期几 这里是:1-7.周日是1,周一是2,。。。周六是7
设置日期
GregorianCalendar calendar2 = new GregorianCalendar(); calendar2.set(Calendar.YEAR, 2999); calendar2.set(Calendar.MONTH, Calendar.FEBRUARY); // 月份数:0-11 calendar2.set(Calendar.DATE, 3); calendar2.set(Calendar.HOUR_OF_DAY, 10); calendar2.set(Calendar.MINUTE, 20); calendar2.set(Calendar.SECOND, 23); printCalendar(calendar2);
日期计算
GregorianCalendar calendar3 = new GregorianCalendar(2999, 10, 9, 22, 10, 50); calendar3.add(Calendar.MONTH, -7); // 月份减7 calendar3.add(Calendar.DATE, 7); // 增加7天 printCalendar(calendar3);
日历对象和时间对象转化
Date d = calendar3.getTime(); GregorianCalendar calendar4 = new GregorianCalendar(); calendar4.setTime(new Date()); long g = System.currentTimeMillis();
Math类
Math类的常用方法:
1. abs 绝对值 Math.abs(-3);//3
2. acos,asin,atan,cos,sin,tan 三角函数
3. sqrt 平方根 Math.sqrt(64);//8.0
4. pow(double a, double b) a的b次幂 Math.pow(5,2);//25.0
5. max(double a, double b) 取大值
6. min(double a, double b) 取小值
7. ceil(double a) 大于a的最小整数 Math.ceil(3.2);//4.0
8. floor(double a) 小于a的最大整数 Math.floor(3.2);//3.0
9. random() 返回 0.0 到 1.0 的随机数 Math.random();//[0,1) 随机小数
10. long round(double a) double型的数据a转换为long型(四舍五入) Math.round(3.2);//3
11. toDegrees(double angrad) 弧度->角度
12. toRadians(double angdeg) 角度->弧度
Random rand=new Random();rand.nextDouble() //随机double小数rand.nextInt() //随机int类型允许范围之内的整型数rand.nextFloat() //随机float小数rand.nextBoolean() //随机true或者falserand.nextInt(10) //随机[0,10)的整型数20+rand.nextInt(10) //随机[20,30)的整型数
File类的基本用法
文件的创建
import java.io.File //代表文件和目录File f=new File("d:/a.txt");//目录地址File f=new File("d:a.txt");f.renameTo(new File("d:/bb.txt")); //改名System.out.println(System.getProperty("user.dir"));//项目路径File f2=new File("gg.txt");f2.createNewFile();
File类访问属性的方法列表
测试File类访问属性的基本用法
File f = new File("d:/b.txt"); System.out.println("File是否存在:"+f.exists()); System.out.println("File是否是目录:"+f.isDirectory()); System.out.println("File是否是文件:"+f.isFile()); System.out.println("File最后修改时间:"+new Date(f.lastModified())); System.out.println("File的大小:"+f.length()); System.out.println("File的文件名:"+f.getName()); System.out.println("File的目录路径:"+f.getPath()); System.out.println("File的决定路径:"+f2.getAbsolutePath());
通过File对象创建空文件或目录(在该对象所指的文件或目录不存在的情况下)
使用mkdir创建目录
public static void main(String[] args) throws Exception { File f = new File("d:/c.txt"); f.createNewFile(); // 会在d盘下面生成c.txt文件 f.delete(); // 将该文件或目录从硬盘上删除 File f2 = new File("d:/电影/华语/大陆"); boolean flag = f2.mkdir(); //目录结构中有一个不存在,则不会创建整个目录树 System.out.println(flag);//创建失败 }
使用mkdirs创建目录
public static void main(String[] args) throws Exception { File f = new File("d:/c.txt"); f.createNewFile(); // 会在d盘下面生成c.txt文件 f.delete(); // 将该文件或目录从硬盘上删除 File f2 = new File("d:/电影/华语/大陆"); boolean flag = f2.mkdirs();//目录结构中有一个不存在也没关系;创建整个目录树 System.out.println(flag);//创建成功 }
递归打印目录树
File f=new File("名 "){ printFile(f,0);}static void printFile(File file,int level){ System.out.println(file.getName()); if(file.isDirectory()){ File[] files=file.listFiles(); for(File temp:files){ printlnFile(temp,level+1); } }}
枚举
所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的成员实质就是一个枚举类型的实例,他们默认都是public static final修饰的。可以直接通过枚举类型名使用它们。
enum 枚举名 { 枚举体(常量列表)}
当你需要定义一组常量时,可以使用枚举类型。
enum Season { SPRING, SUMMER, AUTUMN, WINDER }Season a=Season.AUTUMN;switch(a){case SPRING: System.out.println("春天"); break; case SUMMER: System.out.println("夏天"); break; case AUTUMN: System.out.println("秋天"); break; case WINDTER: System.out.println("冬天"); break;}
美好的人生需要不懈的毅力,漫长的学习道路还很漫长。
加油!!!



