目录
一. 内部类
概念:
- 在一个类的内部再定义一个完整的类
特点:
- 编译之后可生成独立的字节码文件
- 内部类可直接访问外部类的私有成员,而不破坏封装
1. 成员内部类
- 在类的内部定义,与实例变量、实例方法同级别的类
- 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
- Outer out = new Outer();
- Inner in = out.new Inner();
- 当外部类、内部类存在重名属性时,会优先访问内部类属性
- 成员内部类不能定义静态成员,但可以定义静态常量
2. 静态内部类
- 不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员
- 只能直接访问外部类的静态成员(实例成员需实例化外部类对象)
- Outer.Inner inner = new Outer.Inner();
- Outer.Inner.show();
3. 局部内部类
-
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
-
不能加任何访问修饰符
-
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final(jdk1.8以后隐式添加final)
-
限制类的使用范围
4. 匿名内部类
- 没有类名的局部内部类(一切特征都与局部内部类相同)
- 必须继承一个父类或者实现一个接口
- 定义类、实现类、创建对象的语法合并、只能创建一个该类的对象
- 优点:减少代码量
- 缺点:可读性较差
二. 常用类
1. Object
- 超类、基类,所有类的直接或间接父类,位于继承树的最顶层
- 任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
- Object类中所定义的方法,是所有对象都具备的方法
- Object类型可以存储任何对象
- 作为参数,可接受任何对象
- 作为返回值,可返回任何对象
(1) getClass()方法
- public final CLass<?> getClass() {}
- 返回引用中存储的实际对象类型
- 应用:通常用于判断两个引用中实际存储对象类型是否一致
(2) hashCode()方法
- public int hashCode() {}
- 返回该对象的哈希码值
- 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值
- 一般情况下相同对象返回相同哈希码
(3) toString()方法
- public String toString () {}
- 返回该对象的字符串表示(表现形式)
- 可以根据程序需求覆盖该方法,如:展示对象各个属性值
(4) equals()方法
- public boolean equals (Object obj) {}
- 默认实现为(this == obj),比较两个对象地址是否相同
- 可进行覆盖,比较两个对象的内容是否相同
(5) finalize()方法
- 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
- 垃圾对象:没有有效引用指向此对象时,为垃圾对象
- 垃圾回收:由Gc销毁垃圾对象,释放数据存储空间
- 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
- 手动回收机制:使用System.gc(); 通知JVM执行垃圾回收
public class TestStudent {
public static void main(String[] args) {
System.out.println("=====getClass()方法=====");
//1. getClass()方法
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 19);
//判断s1和s2是否是同一类型
Class class1 = s1.getClass();
Class class2 = s2.getClass();
if (class1 == class2){
System.out.println("student和student1属于同一类型");//student和student1属于同一类型
}else{
System.out.println("student和student1不属于同一类型");
}
System.out.println("=====hashCode()方法=====");
//2. hashCode()方法
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
Student s3=s1;
System.out.println(s3.hashCode());
System.out.println("=====toString()方法=====");
//3. toString()方法
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println("=====equals()方法=====");
//4. equals()方法
System.out.println(s1.equals(s2));
Student s4 = new Student("王五", 20);
Student s5 = new Student("王五", 20);
System.out.println(s4.equals(s5));
}
}
2. 包装类
- 基本数据类型所对应的引用数据类型
- Object可统一所有数据,包装类的默认值是null
基本数据类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
类型转换
基本类型和引用类型
装箱:基本类型转成引用类型的过程
拆箱:引用类型转成基本类型的过程
public class Demo01 {
public static void main(String[] args) {
//JDK 1.5之前
//类型转换
//装箱:基本类型转成引用类型的过程
int num = 10;
Integer integer = new Integer(num);
Integer integer1 = Integer.valueOf(num);
System.out.println("装箱");
System.out.println(integer);
System.out.println(integer1);
//类型转换
//拆箱:引用类型转成基本类型的过程
Integer integer2 = new Integer(100);
int num2 = integer2.intValue();
System.out.println("拆箱");
System.out.println(num2);
//JDK1.5之后,提供自动装箱和开箱功能
int age = 30;
//自动装箱
Integer integer3 = age;
System.out.println("自动装箱");
System.out.println(integer3);
//自动拆箱
int age2 = integer3;
System.out.println("自动拆箱");
System.out.println(age2);
//1. 基本类型转字符串
//1.1 使用“+”
int i = 255;
int i1 = 1;
System.out.println(i+i1+"");//256 字符串在后面,相加
System.out.println(""+i+i1);//2551 字符串在前面,拼接
String s = i + "";
System.out.println(s);//255
//1.2 Integer.toString()
String s2 = Integer.toString(i);
System.out.println(s2);//255
//toString重载,输出i的radix进制数
String s3 = Integer.toString(i, 16);
System.out.println(s3);//ff
//2. 字符串转基本类型
String str = "100";
//使用Integer.parseInt()
int i2 = Integer.parseInt(str);
System.out.println(i2);//100
//boolean字符串形式转成基本类型,"true"=>true,只要不是"true",都是false
String str2 = "true";
boolean b = Boolean.parseBoolean(str2);
System.out.println(b);//true
}
}
整数缓冲区(-128~127)
- java预先创建了256个常用的整数包装类型对象
- 在实际应用当中,对已创建的对象进行复用
public class Demo02 {
public static void main(String[] args) {
//Integer缓冲区-128~127
Integer integer = new Integer(100);
Integer integer1 = new Integer(100);
System.out.println(integer == integer1);//false
Integer integer2 = Integer.valueOf(100);
Integer integer3 = Integer.valueOf(100);
//在缓冲区里,值一样,引用对象也相同
System.out.println(integer2 == integer3);//true
Integer integer4 = Integer.valueOf(100);
Integer integer5 = Integer.valueOf(100);
//不在缓冲区里,则重新在堆里面new一个对象,所以两个不同的对象的引用也不同
System.out.println(integer4 == integer5);//false
}
}
3. String
- 字符串是常量,创建后不可改变
- 字符串字面值存储在字符串池中,可以共享
常量池概念:
Java运行时会维护一个String Pool(String池), 也叫“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。
String对象的创建很讲究,关键是要明白其原理。
原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个s在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
原理2:Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
原理3:使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
原理4:使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。最后指向堆内存中的对象
public class Demo01 {
public static void main(String[] args) {
//1. 先定义一个名为str的对String类的对象引用变量:String str;
String str1 = "aaa";//字符串常量存储在方法区的字符串池中
//2. 在池中查找有没有存放值为"aaa"的地址,如果没有,则开辟一个存放字面值为"aaa"的地址
//接着创建一个新的String类的对象o,并将o 的字符串值指向这个地址,而且在池中这个地址旁边记下这个引用的对象o。如果已经有了值为"aaa"的地址,则查找对象o,并返回o的地址。
//3. 将str指向对象o的地址
//当我们将str1的值改为"bbb"时,JVM发现在池中没有存放该值的地址,便开辟了一个存放字面值为"bbb"的地址,并创建了一个新的对象,其字符串的值指向这个地址
str1 = "bbb";
String str2 = "bbb";//JVM 创建str2,并指向“bbb”
System.out.println(str1 == str2);//true
//总结就是:JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象
//1、 使用new关键字
String s1 = new String("ab"); //产生两个对象,堆、池中各存一个
//2、 使用字符串常量直接赋值
String s2 = "abc";
//3、 使用”+”运算符进行字符串连接
String s3 = "abc" + "d";
String s4 = s3 + 5; //abcd5
System.out.println("=======================");
String n1 = new String("java");
String n2 = new String("java");
System.out.println(n1 == n2);//false,n1和n2分别指向堆中的两个对象
System.out.println(n1.equals(n2));//true
}
}
(1)常用方法
- public int length():返回字符串的长度
- public char charAt(int index):根据下标获取字符
- public boolean contains(String str):判断当前字符串是否包含str
- public char[] toCharArray():将字符串转化为数组
- public int indexOf(String str):查找str首次出现的下标,存在,则返回该下标;不存在,则返回-1
- public int lastIndexOf(String str):查找str最后一次出现的下标索引
- public String trim():去掉字符串前后的空格
- public String toUpperCase():将小写转成大写
- public boolean endWith(String str):判断字符串是否以str结尾
- public String replace(char oldChar,char newChar):将旧字符串替换成新的字符串
- public String[] split(String str):根据str做拆分
- public String substring(int beginIndex, int endIndex):截取父字符串的一部分,结尾参数可去掉
public class Demo02 {
public static void main(String[] args) {
//1. length():返回字符串的长度
//2. charAt(int index):根据下标获取字符
//3. contains(String str):判断当前字符串是否包含str
String s = "java是世界上最好的语言";
System.out.println(s.length());//13
System.out.println(s.charAt(0));//首位字符 j
System.out.println(s.charAt(s.length()-1));//末尾字符 言
System.out.println(s.contains("java"));//true
System.out.println(s.contains("Php"));//false
//4. toCharArray():将字符串转化为数组
//5. indexOf(String str):查找str首次出现的下标,存在,则返回该下标;不存在,则返回-1
//6. lastIndexOf(String str):查找str最后一次出现的下标索引
System.out.println(Arrays.toString(s.toCharArray()));//[j, a, v, a, 是, 世, 界, 上, 最, 好, 的, 语, 言]
System.out.println(s.indexOf("a"));//1
System.out.println(s.lastIndexOf("a"));//3
//7. trim():去掉字符串前后的空格
//8. toUpperCase():将小写转成大写
//9. endWith(String str):判断字符串是否以str结尾
String s2 = " asd ";
String s3 = s2.trim();
System.out.println(s3);//asd
String s4 = s3.toUpperCase();
System.out.println(s4);//ASD 转为大写字母
String s5 = s4.toLowerCase();
System.out.println(s5);//asd 转为小写字母
String filename = "hello.java";
System.out.println(filename.endsWith(".java"));//true
//10. replace(char oldChar,char newChar):将旧字符串替换成新的字符串
//11. split(String str):根据str做拆分
System.out.println("==========");
System.out.println(s.replace("java","php"));
String s1 = "java is the best language of the world, java is good";
String[] arr = s1.split("[ ,]+");//[ ,]表示以空格或者逗号作为分隔符,+表示空格和逗号可以出现多次
System.out.println(arr.length);//11
for (String s6 : arr) {
System.out.println(s6);
}
//字符串String的split方法, 传入的分隔字符串是正则表达式!
// 部分关键字(比如.[]()|等)需要转义
String str = "a.ab.abc";
String str1 = "a|ab|abc";
System.out.println(Arrays.toString(str.split("\.")));//[a, ab, abc]
System.out.println(Arrays.toString(str1.split("\|")));//[a, ab, abc]
//补充:equals,compareTo()
System.out.println("---------------");
String s6 = "hello";
String s7 = "Hello";
System.out.println(s6.equalsIgnoreCase(s7));//true 忽略大小写
String s8 = "abc";//97
String s9 = "xyz";//120
System.out.println(s8.compareTo(s9));//-23
String s10 = "abc";//3
String s11 = "abcxyz";//6
System.out.println(s10.compareTo(s11));//-3,比较长度
}
}
public class TestDemo02 {
public static void main(String[] args) {
String str = "this is a text";
//1.将str中的单词单独获取出来
String[] arr = str.split(" ");
for (String s : arr) {
System.out.println(s);
}
//2.将str中的text替换为practice
String str2 = str.replace("text", "practice");
System.out.println(str2);
//3.在text前面插入一个easy
String str3 = str.replace("text", "easy text");
System.out.println(str3);
//4.将每个单词的首字母该为大写
//substring截取父字符串的一部分
for (int i = 0; i < arr.length; i++) {
char first = arr[i].charAt(0);
//把第一个字母转成大写
char upperFirst = Character.toUpperCase(first);
String news = upperFirst + arr[i].substring(1);
System.out.println(news);
}
}
}
(2)StringBuffer和StringBuilder
- StringBuffer:可变长字符串,JDK1.0提供,运行效率慢、线程安全
- StringBuilder:可变长字符串,JDK5.0提供,运行效率块、线程不安全
public class Demo03 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
//1. append(); 追加
sb.append("张三");
System.out.println(sb.toString());
sb.append("李四");
System.out.println(sb.toString());
sb.append("王五");
System.out.println(sb.toString());
//2. insert(); 添加
sb.insert(0, "第一");
System.out.println(sb.toString());
//3. replace(); 替换
sb.replace(0,2,"第二");
System.out.println(sb.toString());
//4. delete(); 删除
sb.delete(0,2);
System.out.println(sb.toString());
}
}
//测试StringBuilder和String的速度
public class TestDemo03 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
// String string = "";
// for (int i = 0; i < 99999; i++) {
// string += i;
// }
// System.out.println(string);//28791 String用时28.791秒
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 99999; i++) {
stringBuilder.append(i);
}
System.out.println(stringBuilder);//74 StringBuilder用时0.074秒,速度比String快太多了
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
}
4.BigDecimal
- 位置:java.math包中
- 作用:精确计算浮点数
- 创建方式:BigDecimal bd = new BigDecimal("1.0");
public class Demo01 {
public static void main(String[] args) {
double d1 = 1.0;
double d2 = 0.9;
System.out.println(d1 - d2);
//面试题
double result = (1.4-0.5)/0.9;
System.out.println(result);
//BigDecimal 大的浮点数的精确计算
BigDecimal bd = new BigDecimal("1.0");
BigDecimal bd1 = new BigDecimal("0.9");
//加法
BigDecimal r1 = bd.add(bd1);
System.out.println(r1);
//减法
BigDecimal r = bd.subtract(bd1);
System.out.println(r);
//乘法
BigDecimal r2 = bd.multiply(bd1);
System.out.println(r2);
//除法
BigDecimal result1 = new BigDecimal("1.4")
.subtract(new BigDecimal("0.5"))
.divide(new BigDecimal("0.9"));
System.out.println(result1);
BigDecimal result2 = new BigDecimal("20").divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_UP);
System.out.println(result2);
//除法:divide(BigDecimal bd, int scale, RoundingMode mode)
//参数scale:指定精确到小数点后几位
//参数mode:指定小数部分的取舍模式,通常采用四舍五入模式,取值为BigDecimal.ROUND_HALF_UP
}
}
5. Date
- Date表示特定的瞬间,精确到毫秒。Date类中的大部分方法都已被Calendar类中的方法所取代
- 时间单位
- 1秒=1000毫秒
- 1毫秒=1000微秒
- 1微秒=1000纳秒
public class Demo01 {
public static void main(String[] args) {
//1.创建Date对象
Date date = new Date();
System.out.println(date.toString());
System.out.println(date.toLocaleString());
Date date1 = new Date(date.getTime()-(60*60*24*1000));
System.out.println(date1.toLocaleString());
//2.方法after before
boolean b1 = date.after(date1);
System.out.println(b1);
boolean b2 = date.before(date1);
System.out.println(b2);
//比较 compareTo()
int i = date.compareTo(date1);
System.out.println(i);
//equals()
boolean b = date.equals(date1);
System.out.println(b);
}
}
6. Calendar
- Calendar提供了获取或设置各种日历字段的方法
- 构造方法
- protected Calendar():由于修饰符是protected,所以无法直接创建该对象
public class Demo01 {
public static void main(String[] args) {
//1. 创建Calendar
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime().toLocaleString());
System.out.println(calendar.getTimeInMillis());
//2. 获取时间信息
//获取年
int year = calendar.get(Calendar.YEAR);
//月
int month = calendar.get(Calendar.MONTH);
//日
int day = calendar.get(Calendar.DAY_OF_MONTH);//DATE
//小时
int hour = calendar.get(Calendar.HOUR_OF_DAY);//HOUR_OF_DAY 24h,HOUR 12h
//分钟
int minute = calendar.get(Calendar.MINUTE);
//秒
int second = calendar.get(Calendar.SECOND);
System.out.println(year + "-" +
(month+1) + "-" +
day + " " +
hour + ":" +
minute + ":" +
second);
//3. 修改时间 set
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.DAY_OF_MONTH, 23);//日期变为23号
System.out.println(calendar1.getTime().toLocaleString());
//4. 修改时间 add
calendar1.add(Calendar.HOUR, -1);//减少一小时
System.out.println(calendar1.getTime().toLocaleString());
//5. 补充方法
int max = calendar1.getActualMaximum(Calendar.DAY_OF_MONTH);//计算本月最大天数
int min = calendar1.getActualMinimum(Calendar.DAY_OF_MONTH);//计算本月最小天数
System.out.println(max);
System.out.println(min);
}
}
7.SimpleDateFormat
- SimpleDateFormat是一个以 与语言环境有关的方式 来 格式化和解析日期 的具体类
- 进行格式化(日期 -> 文本)、解析(文本 -> 日期)
- 常用的时间模式字母
字母 | 日期或时间 | 示例 |
---|---|---|
y | 年 | 2021 |
M | 年中月份 | 02 |
d | 月中天数 | 24 |
H | 1天中小时数(0~23) | 11 |
m | 分钟 | 46 |
s | 秒 | 59 |
S | 毫秒 | 345 |
public class Demo01 {
public static void main(String[] args) throws ParseException {
//1. 创建SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//2. 创建Date
Date date = new Date();
//格式化date(日期转字符串)
String str = sdf.format(date);
System.out.println(str);
//解析(字符串转时间)
Date date1 = sdf.parse("2021年02月24日 12:05:42");
System.out.println(date1);
}
}
8. System
- System系统类,主要用于获取系统的属性数据和其他操作,构造方法是私有的
static void arraycopy(...) //1.复制数组
static long currentTimeMillis();//2.获取当前系统时间,返回的是毫秒值
static void gc();//3.建议JVM赶快启动垃圾回收器回收垃圾
static void exit(int status);//4.退出JVM,如果参数是0表示正常退出JVM,非0表示异常退出JVM
public class Demo01 {
public static void main(String[] args) {
//1. 数组的复制arraycopy
//src:源数组
//srcPos:从哪个位置开始复制0
//dest:目标数组
//destPos:目标数组的位置
//length:复制的长度
int[] array = new int[]{2,4,6,8,10};
int[] dest = new int[5];
System.arraycopy(array,4,dest,2,1);
for (int d : dest) {
System.out.println(d);
}
//2. 获取当前系统时间,返回的是毫秒值currentTimeMillis();
long start = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 99999; i++) {
stringBuilder.append(i);
}
System.out.println(stringBuilder);//74 StringBuilder用时0.074秒,速度比String快太多了
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
//3. 建议JVM赶快启动垃圾回收器回收垃圾gc();
new Student("a", 20);
new Student("b", 20);
new Student("c", 20);
new Student("d", 20);
new Student("e", 20);
//回收垃圾
System.gc();
System.out.println("回收垃圾");
//4. 退出JVM exit();
System.exit(0);
System.out.println("程序结束了......");
}
}