快捷键:
Ctrl+Shift+T ——>打开类型,查看源码Ctrl+O——>查看类中的成员Ctrl+T——>查看当前类的继承结构(层次树),默认是从上向下显示,再按一次从下向上显示关联JDK的源码:
Preferences——>Java——>Installed JREs——>选中安装jre——>Edit——>选中rt.jar——>Source Attachement——>External location——>选择JDK安装路径下的 src.zipAPI文档就是根据文档注释生成的 文档注释以 /** 开头,以 */ 结尾,是一种带有特殊功能的注释 文档注释中可以包含特定的标记,都是以@开头,常用标记:
@author 作者@date 日期@version 版本@see 参考内容@since 从哪个版本开始支持@param 方法参数,格式:@param 参数名称 参数描述@return 方法返回值,格式:@return 返回值描述@throws 方法抛出的异常@exception 方法抛出的异常,作用和@throws相同@override 重写方法@deprecated 已过时,仅为了保证兼容性,不建议使用设置Eclipse自动生成注释:
Preferences—>Java—>Code Style—>Code Templates Comments—>Types—>Edit 为类设置注释模板 /** - @author ${user} - @date ${date}${time} - ${tags} */ Comments—>Methods—>Edit 为方法设置注释模板 /** - <功能描述> - ${tags} - @date ${date} ${time} */ 勾选"Automatically add comments…"生成文档:
使用javadoc工具生成 执行 javadoc Bank.java使用eclipse向导生成 如果出现中文乱码,可以加参数 -encoding utf8java.lang.Object类所有类的根,所有类都直接或间接的继承了Object类 Object类中共有11个方法,都需要掌握
2.1 getClass() 返回对象的运行时类的Class对象,表示运行时类,简单来说,可以认为是字节码文件 主要用于反射(后面会详细讲解) Object类中多个方法都是被 native 关键字修饰的
被 native 修饰的方法,称为本地方法该方法的方法体由非java语言实现,主要用来调用本地的底层语言,如c或c++定义该方法时并不提供方法体,而是使用外部的非java语言实现 //所有类继承自Object类,即继承了Object类中的成员 User user = new User(); user.toString(); user.hashCode(); System.out.println(user.toString()); System.out.println(user.hashCode()); System.out.println(user.getClass()); User VIPUser = new VIPUser(); System.out.println(VIPUser.getClass()); System.out.println(user.equals(VIPUser)); if (user.getClass() == VIPUser.getClass()) { ((VIPUser)user).show(); }2.2 equals() equals和==的区别:
==判断是否引用同一个对象,比较的是栈中的equals如果没有被重写,则默认和==没区别,因为Object的equals()就是使用==来判断的如果重写了equals,则按重写后的比较规则进行比较 说明:自定义类可以重写equals()方法来实现对特定字段的等值判断可以通过开发工具快速重写equals方法 User user = new User(); User user2 = new User(); System.out.println(user == user2); System.out.println(user.equals(user2));2.3 hashCode() 返回对象的hashCode值,即哈希码值
hashCode是为了支持数据结构的哈希表hash table如果没有重写该方法,默认返回的是对象的内存地址重写equals()方法时,务必要重写hashCode()方法特性:
多次调用同一个对象的hashCode方法,必须返回相同的值如果两个对象的equals比较为true,则两个对象的hashCode值也应该相同如果两个对象的equals比较为false,不强制要求两个hashCode值不相同,但为不同对象产生不同的 hashCode值可以提升哈希表的性能(讲集合时会详细讲解) User user = new User(); User user2 = new User(); System.out.println(user.hashCode()); System.out.println(Integer.toHexString(user.hashCode())); System.out.println(user2.hashCode()); System.out.println(Integer.toHexString(user2.hashCode()));//输出hash值得十六进制2.4 toString() 将对象转换为字符串表示形式
当直接输出对象时,会自动调用对象的toString()方法,即本质上输出的是toString()方法的返回值如果没有重写该方法,默认返回值: 类全名@十六进制的hashCode值通过重写该方法,输出对象时可以返回更易读的信息,便于查看结果,一般用于测试2.5 clone() 用于克隆对象 对象被克隆的要求:
必须重写clone()方法,且要调用super.clone()方法类必须实现 Cloneable 接口,表示该类可以被克隆浅克隆和深克隆:
浅克隆(浅复制)从Object继承的clone()方法默认是浅克隆,只克隆对象本身,不克隆它所引用的对象,即只克隆第一层 所有的对其他对象的引用仍然指向原来的对象深克隆(深复制) 把要克隆的对象所引用的其他对象都克隆一遍 所有的对其他对象的引用都将指向被克隆的新对象 需要自己实现,对所有引用的其他对象进行再次克隆 @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }2.6 finalize() 该方法不需要程序员手动调用,由垃圾回收器自动调用
垃圾回收机制:
JVM中存在有一个守护线程,叫做gc:garbage collector 垃圾回收器gc的作用: 每个对象上,都会存在一个int类型的变量,叫做引用计数器 每当有一个引用指向该对象时,引用计数+1 每当有一个引用不再指向该对象时,引用计数1 当引用计数值为0时,gc认为该对象为 垃圾 gc会在合适的时机(算法)对该对象进行回收,释放资源 当对象被gc回收时,gc会自动调用finalize()方法 可以通过执行 System.gc() ,建议JVM进行垃圾回收java.lang.String 字符串就是一个字符序列,由多个字符组成,是Java中最常用的类型
public final class String implements java.io.Serializable, Comparable<String>, CharSequence,创建字符串的方式:
直接创建使用构造方法创建 /* * 1、直接创建 * 该方式本身来说是不符合引用类型的特点,不符合面向对象的规范 * 原则上来说,所有引用类型都应该通过new关键来创建对象,只有基本数据类型才能直接赋值 * String是一种特殊的引用类型,由于特别常用,所以JVM对其做了优化 */ String a1 = "hello"; /* * 2、使用构造方法创建 */ String b1 = new String(); String b2 = new String("qqqqq"); //空字符串和null的区别 String c1 = "";//在堆内存中分配了内存,但为空字符串 String c2 = null;//在堆内存中没有分配 空间 //string类型可以和任意类型进行+的操作,效果就是拼接 System.out.println("111"+"aaa");字符 Character:是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等 字符集 Charset:是多个字符的集合,字符集种类很多,每个字符集包含的符号个数不同 常见字符集:ASCII、ISO88591、GB2312、GBK、UTF8 注:Windows系统默认使用GBK,Linux和MacOS系统默认使用UTF-8
/** * 字符集 */ public static void Test01() { System.out.println("当前系统的使用的字符集:"+System.getProperty("file.encoding")); System.out.println("当前JVM的字符集:"+Charset.defaultCharset()); }由于计算机底层使用二进制,只认识0和1,所以在处理各种字符时,需要对字符进行编码和解码,以便计算机 能够识别和存储 编码和解码:
将字符串转换为字节数组,称为编码将字节数组转换为字符串,称为解码 /** * 编码和解码 * @throws UnsupportedEncodingException */ public static void Test02() throws UnsupportedEncodingException { String s = "您好"; /* * 编码 */ byte[] bytes = s.getBytes("gbk"); System.out.println(Arrays.toString(bytes)); /* * 解码 */ String s2 = new String(bytes,"gbk"); System.out.println(s2); }在编码和解码时需要使用所使用的字符集乱码:编写程序时,由于字符集设置不对或编码和解码时使用了不一致的字符集,导致出现了乱码
4.1 简介 正则表达式是一门独立的语言,有自己的语法,用于检测指定字符串是否符合特定规则 正则表达式就是用来定义规则的
4.2 规则 规则的定义
示例作用a只能是aaba{5}只能是a,并且有5位a{5,}只能是a,至少有5位a{5,7}只能是a,5到7位a*只能是a,0到多位,即可有可无a+只能是a,1到多位,即至少有1位a?只能是a,0到1位[a-g]{5}只能是a到g,并且有5位[a-zA-Z]{5}只能是字母,忽略大小写,并且有5位[0-9a-zA-Z]{2,}只能是数字、字母,至少有2位.任意一个字符\d数字,\表示正则转义符\D非数字\w数字、字母、下划线\W非(数字、字母、下划线)\s空格\S非空格\n回车\t制表符4.3用法 String中支持正则表达式的方法:
方法名作用matches判断字符串是否匹配某个规则replaceAll作用和replace一样,区别在于支持正则replaceFirst作用和replaceAll一样,区别是只替换第一个split使用正则,将字符串分割为数组字符串的值一旦确定,则不可修改 不可修改 指的是内存中的值不能再修改,不是变量不能修改
//字符串不变性 /* * 基本数据类型 */ int i = 3; i = 6;// 内存中只有一个变量值6,3的值会被6覆盖 /* * 字符串,引用数据类型 */ String str1 = "tom"; str1 = "jack";// 当重新赋值时会在内存中再分配一块空间,创建一个新的String,所以内存中有两个String对象,分别是tom和jackString常量:使用双引号直接创建的字符串,称为String常量,即字符常量
字符常量被存放在内存的常量池中常量池中的值不会被gc回收,即gc不会清理这个区域中的内容多次出现的相同字符常量,只会在常量池中创建一个Sring对象(JVM做了优化)常量池的位置:
jdk1.6中,常量池在方法区的PermGen Space永久代中(就是一个永久保存区域)jdk1.7中,常量池在堆内存中jdk1.8中,常量池在元空间中,和堆相独立 /* * 使用构造方法创建字符串 */ // 存放在堆中,强制在堆内存中开辟一块新空间(只要是new出来的,必须会在堆中分配新的内存 String str1 = new String("aaa");//第1个对象 //第2个对象 str1 = new String("bbb");// 由于aaa不再被任何引用所指向,所以会gc回收 /* * 使用双引号直接创建字符串 */ //第3个对象 String str2 = "aaa";// 字符常量,存放在常量池中 //第4个对象 str2 = "bbb";// 内存的常量池中会有两个String对象,分别是aaa和bbb,且不会被gc回收 /* * 多次出现的相同字符常量,只会在常量池中创建一个String对象 */ String str3 = "bbb";// 创建流程:先判断常量池是否有bbb,如果有则直接指向常量池中的bbb,如果没有则在常量池中创建bbb System.out.println(str3 == str1);//false System.out.println(str3 == str2);//true String str4 = new String("bbb");//第5个对象 System.out.println(str4 == str1);//false System.out.println(str4 == str2);//false //问题 String str5 = "bb";//第6个对象 String str6 = "b";//第7个对象 //问题1: //第8个对象 String str7 = str5+str6;//s7不是字符常量,不是使用双引号直接创建的字符串,而是在运行时计算得到的 System.out.println(str7 == str2);//false //问题2: String str8 = "bb"+"b";//s8是字符常量,对于常量和常量的运算,在编译期已经得到了值(编译器做了优化) System.out.println(str8 == str2);//true //问题3: //第9个对象 String str9 = str5 + "b";//s9不是字符常量,在编译期无法确定s9的值 System.out.println(str9 == str2);//false //4 创建了多少个对象:9个(具体见注释)String是不可变字符串,不可修改
频繁对String进行修改时会在内存中产生许多对象,垃圾数据String类中提供了许多方法,但没有 增删改 等操作的方法 如果需要频繁对字符串进行修改操作,建议使用StringBuffer和StringBuilder,它们是可变字符串这两个类的用法基本一致StringBuffer
线程安全(多个人同时访问一个字符串,不会出现问题)效率低StringBuilder
线程不安全(多个人同时访问一个字符串,可能会出现问题)效率高 String str = ""; StringBuffer buffer = new StringBuffer(); StringBuilder builder = new StringBuilder(); long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { str += "hello"; } long endString = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { buffer.append("hello"); } long endbuffer = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { builder.append("hello"); } long endbuilder = System.currentTimeMillis(); System.out.println("花费的时间:"+(endString-start)); System.out.println("花费的时间:"+(endbuffer-endString)); System.out.println("花费的时间:"+(endbuilder-endbuffer));基本数据类型功能比较简单,不具有面向对象的特性 Java中为每个基本数据类型都提供了一个对应的包装类,使其具有面向对象的特性
基本数据类型对应的包装类byteByteshortShortintintegerlongLongfloatFloatdoubleDoublecharCharbooleanBoolean装箱和拆箱:
将基本数据类型转换为包装类,称为装箱将包装类转换为基本数据类型,称为拆箱 在JDK1.5以前,需要手动装箱和拆箱,即手动进行转换 在JDK1.5及以后,支持自动装箱和拆箱,即自动进行转换 /* * 基本数据类型和包装类进行运算,会自动进行拆箱 */ int m = 6; Integer n = new Integer(8); int p = m+n; int x = 3; Integer y = new Integer(3); Integer z = new Integer(3); System.out.println(y==z); System.out.println(x==z);// 因为z在进行运算时发生了自动拆箱 Object object = 5;//先自动装箱,然后多态1.1 简介 java.util.Date 表示日期 Java底层使用long类型表示日期
long类型的值表示的是当前时间的毫秒值 这个毫秒值是基于 1970年1月1日 0时0分0秒 的差值,这个时间被认为是计算机的起始时间(纪元时间)Date类中有多个构造方法都是过时的,不建议使用
1.2 常用方法
Date date = new Date(); // getYear()、getMonth()、getDate()、getHours()等,都已过时 // getTime() 获取毫秒值 System.out.println(date.getTime()); //setTime() 设置毫秒值 date.setTime(6666); System.out.println(date); //after() 判断某个日期是否在指定日期之后 Date date2 = new Date(222); Date date3 = new Date(111); System.out.println(date3.after(date2)); // before() 判断某个日期是否在指定日期之前 System.out.println(date3.before(date2)); /* * a.compareTo(b) 对两个日期进行比较 * 如果a>b,则返回1,如果a<b,则返回1,如果a==b,则返回0 */ Date date4 = new Date(111); System.out.println(date4.compareTo(date3)); System.out.println(date4.compareTo(date2)); System.out.println(date4.compareTo(date));1.3 Date和String的转换 使用 java.text.SimpleDateFormat 日期格式化类,继承自DateFormat 格式化字符串,参考API文档中的SimpleDateFormat
/* * 将日期转换为字符串 */ // 1.创建SimpleDateFormat对象,指定目标格式,如 2019214 12:30:25 Date date = new Date(); DateFormat df = new SimpleDateFormat("E yyyy年MM月dd日 HH:mm:ss"); // 2.调用format()进行格式化 String str = df.format(date); System.out.println(str); /* * 将字符串转换为日期 */ String s="2008年12月8日"; // 1.创建SimpleDateFormat对象,指定字符串的日期格式 DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日"); // 2.调用parse()解析为日期 Date date2 = df2.parse(s); System.out.println(date2);2.1 简介 java.util.Calendar表示日历,用于日期的运算和取值 Calendar是一个抽象类,不能通过new来创建,使用静态方法getInstance()获取一个实例
2.2 常用方法
// 创建一个Calendar实例 Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getClass()); /* * 常用方法 */ //getTime()将Calendar转换为Date Date date = calendar.getTime(); System.out.println(date); System.out.println(DateUtil.toString(date)); // setTime() 设置时间为指定的Date calendar.setTime(new Date(888888888)); System.out.println(calendar.getTime()); System.out.println(DateUtil.toString(calendar.getTime())); // get() 获取日期的指定字段 System.out.println(calendar.get(Calendar.YEAR));// 年 System.out.println(calendar.get(Calendar.MONTH) + 1);// 月,返回值为011,0表示1月 System.out.println(calendar.get(Calendar.DATE));// 日 System.out.println(calendar.get(Calendar.DAY_OF_MONTH));// 一个月的第几天,等同于DATE System.out.println(calendar.get(Calendar.DAY_OF_WEEK));// 一周的第几天,返回值为17,1表示第1天(星期天) System.out.println(calendar.get(Calendar.DAY_OF_YEAR));// 一年的第几天 System.out.println(calendar.get(Calendar.HOUR));// 时,12小时制 System.out.println(calendar.get(Calendar.HOUR_OF_DAY));// 24小时制 System.out.println(calendar.get(Calendar.MINUTE));// 分 System.out.println(calendar.get(Calendar.SECOND));// 秒 System.out.println(calendar.get(Calendar.MILLISECOND));// 毫秒 //set()设置日期时间 calendar.set(calendar.YEAR, 2020);// 指定的field System.out.println(calendar.get(Calendar.YEAR)); calendar.set(2020, 7, 13);// 月份从0开始,1表示二月 System.out.println(DateUtil.toString(calendar.getTime())); calendar.set(2020, Calendar.DECEMBER, 13, 24, 800);// 使用常量 System.out.println(DateUtil.toString(calendar.getTime())); //add() 添加日期时间 calendar.add(Calendar.YEAR, 2);//+2年 System.out.println(DateUtil.toString(calendar.getTime())); //clear()情况 // calendar.clear(); //getTimeInMillis() 毫秒值 System.out.println(calendar.getTimeInMillis()); System.out.println(System.currentTimeMillis());java.lang.Math用于执行数学运算 Math类中所有方法都是静态方法
/* * 常量 */ System.out.println(Math.PI);//圆周率 System.out.println(Math.E);//自然对数 /* * 方法 */ double a = 3.758; //round()四舍五入 System.out.println(Math.round(a));// 返回long类型 System.out.println(Math.round(a*100)/100.0);//保留两位小数 // floor()返回小于等于参数的最大整数 System.out.println(Math.floor(a)); // ceil()返回大于等于参数的最小整数 System.out.println(Math.ceil(a)); //abs()绝对值 System.out.println(Math.abs(-0.9)); //pow()求次方幂 System.out.println(Math.pow(2.5, 3.5)); // random()产生一个[0,1)的随机浮点数 System.out.println(Math.random()); System.out.println((int)(Math.random()*100));// 产生一个[0,100)之间的随机整数 System.out.println((int)(Math.random()*61+20));// 产生一个[20,80]之间的随机整数java.util.Random用于生成随机数
// 创建一个Random实例,随机数生成器 Random random = new Random(); /* * 常用方法 */ // nextInt() 生成一个随机整数 System.out.println(random.nextInt()); System.out.println(random.nextInt(100));// 生成一个[0,100)之间的随机整数 System.out.println(random.nextInt(61)+20);// 产生一个[20,80]之间的随机整数 //nextDouble() System.out.println(random.nextDouble());// nextDouble 生成一个[0,1)之间的随机浮点数,相当于Math.random() // nextBoolean() System.out.println(random.nextBoolean());// nextBoolean() 生成一个随机布尔值 System.out.println(Math.random()>0.5?true:false);