目录
- 1 内部类
- 1.1 成员内部类
- 1.2 静态内部类
- 1.3 局部内部类
- 1.4 匿名内部类
- 2 Object类
- 2.1 getClass()方法
- 2.2 hashCode()方法
- 2.3 toSring()方法
- 2.4 equals()方法
- 2.5 finalize()方法
- 3 包装类
- 3.1 类型转换与装箱、拆箱
- 3.2 整数缓冲区
- 4 String类
- 4.1 常用方法
- 4.2 可变字符串
- 5 BigDecimal类
- 6 时间类型
- 6.1 Date类
- 6.2 Calendar类
- 6.3 SimpleDateFormat类
- 6.4 System类
1 内部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
内部类特点:
1.编译之后会生成独立的字节码文件
2.内部类可直接访问外部类的私有成员,而不破坏封装
3.内部类可以为外部类提供必要的内部功能组件
1.1 成员内部类
在类的内部定义,与实例变量、实例方法同级别的类。
创建内部类对象时,必须依赖外部类对象。
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
或者一步到位:Outer.Inner inner = new Outer().new Inner();
当外部类、内部类存在同名属性时,会优先访问内部类属性。如果需要调用外部类属性,需要使用Outer.this.属性
成员内部类不能定义静态成员,但是可以定义静态常量。
1.2 静态内部类
不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。(相当于外部类)
直接创建静态内部类对象:
Outer.Inner Inner = new Outer.Inner();注意new Outer后面没有括号,即没有创建对象,表明Outer和Inner只是包含关系。
只有静态内部类才能被static修饰,普通类不能被static修饰。
静态内部类调用外部类对象的属性需要使用Outer.属性。
静态内部类自己的的属性和方法直接调用。
1.3 局部内部类
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
不能加任何访问修饰符。
如果需要在其他普通类调用局部内部类里面的方法(方法2),要在外部类的包含了局部内部类的局部方法(方法1)中创建局部内部类对象:
class Outer{方法1(){class Inner{方法2(){}}Inner inner = new Inner();inner.方法2(); }
}
class OtherClass{Outer outer = new Outer();outer.方法1();//这样就可以调用到方法2了
}
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。
访问局部变量 jdk1.7要求局部方法中的变量必须为常量final、jdk1.8自动添加final修饰(只是不显示而已)
1.4 匿名内部类
没有类名的局部内部类(一切特征都与局部内部类相同)。
必须继承一个父类或者实现一个接口。
定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
优点:减少代码量;缺点:可读性较差。
// 使用匿名内部类优化(相当于创建了一个局部内部类)
Usb usb = new Usb(){ // Usb为一个接口/抽象类/父类(多态)@Overridepublic void service(){sout("连接电脑成功,fan开始工作")}
};
usb.service();
2 Object类
- 超类、基类,所有类的直接或间接父类,位于继承树的最顶层
- 任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
- Object类中所定义的方法,是所有对象都具备的方法
- Object类型可以存储任何对象
作为参数,可接受任何对象
作为返回值,可返回任何对象
2.1 getClass()方法
public final Class<?> getClass(){}
返回引用中存储的实际对象类型。
应用:通常用于判断两个引用中实际存储对象类型是否一致。
Class class1 = s1.getClass();
Class class2 = s2.getClass();
// getClass返回 class类型
if(class1==class2){
// 判断s1 和 s2是不是同一个类型
}
2.2 hashCode()方法
public int hashCode(){}
返回该对象的哈希码值。
哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的值。
一般情况下相同对象返回相同哈希码。
2.3 toSring()方法
public String toSring(){}
返回该对象的字符串表示(表现形式)
可以根据程序需求覆盖该方法,如:展示对象各个属性值
2.4 equals()方法
public boolean equals(Object obj){}
默认实现为(this == obj), 比较两个对象地址是否相同。
可进行覆盖,比较两个对象的内容是否相同。
// 判断两个对象是否相等
Student s4 = new Strudent("小明", 17);
Student s5 = new Strudent("小明", 17);
sout(s4.equals(s5)); // false 堆中地址不同// 重写 改变其比较内容
/*
步骤 1. 比较两个应用是否指向同一个对象2. 判断obj是否为null3. 判断两个引用只想的实际对象类型是否一致4. 强制类型转换5. 依次比较各个属性值是否相同
*/
@override
public boolean equals(Object obj){// 1.判断两个对象是否是同一个引用if(this == obj){return true;}// 2.判断obj是否为nullif(obj == null){return false;}// 3.判断是否是同一个类型// if(this.getClass() == obj.getClass()){//// }//最好使用instanceof 判断对象是否是某种类型if(obj instanceof Student){// 4.强制类型转换Student s = (Student)obj;// 5. 比较属性if(this.name.equals(s.getName()) && this.age == s.getAge()){return true;}}return false;
}
2.5 finalize()方法
当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。
垃圾对象:没有有效引用指向此对象时,为垃圾对象。
垃圾回收:由GC销毁垃圾对象,释放数据存储空间。
自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。
手动回收机制:使用System.gc();通知JVM执行垃圾回收。
3 包装类
- 基本数据类型所对应的引用数据类型。
- Object 可统一所有数据,包装类的默认值是null。
基本数据类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
3.1 类型转换与装箱、拆箱
8种包装类提供不用类型间的转换方式:
- Number父类中提供的6个共性方法
- parseXXX( )静态方法
- valueOf( )静态方法
注意:需保证类型兼容,否则抛出NumberFormatException异常
//装箱,基本类型转成引用类型
//拆箱,引用类型转成基本类型
// jdk1.5之后提供了自动装箱拆箱int age = 30;//自动装箱。自动完成了:Integer integer = Integer.valueOf(age);Integer integer = age;//// 自动拆箱。自动完成了该行代码:int age2 = integer.intValue();int age2 = integer;
基本类型和字符串之间转换:
// 1. 基本类型转成字符串int n1 = 100;// 方法1 使用+号String s1 = n1 + "";// 方法2 使用Integer中的toString()方法String s2 = Integer.toString(n1);String s2 = Integer.toString(n1, x); // x为进制要求// 2. 字符串转成基本类型String str = "150";// 使用Integer.parseXXX();int n2 = Integer.parseInt(str);// boolean 字符串形式转成基本类型,"true" ---> true 非“true ———> falseString str2 = "true";boolean b1 = Boolean.parseBoolean(str2);
3.2 整数缓冲区
Java预先在堆内存中创建了256个常用的整数包装类型对象,即[-128,127],当 Integer i =Integer.valueOf(x)处于这个区间之内,就直接将堆内存中的那个值的地址赋给i。如果x相同,i的地址都相同,如果不处于那个区间,则new一个对象。(此为源码解读)
可以参考:低调的洋仔
在实际应用当中,对已创建的对象进行复用(如下面的integer3和integer4例子)
psvm(String[] args){// 面试题Integer integer1 = new Integer(100);Integer integer2 = new Integer(100);sout(integer1 == integer2); // falseInteger integer3 =100;// 自动装箱// 相当于调用 Integer.valueOf(100);Integer integer4 =100;sout(integer3 == integer4); // trueInteger integer5 = 200;// 自动装箱Integer integer6 = 200;sout(integer5 == integer6); // false// 因为缓存区数组 [-128, 127] 在这之内地址一样
}
4 String类
- 字符串是常量,创建之后不可改变
- 字符串字面值存储在字符串池中,可以共享
- String s = “Hello”;产生一个对象,字符串池中存储
- String s = new String(“Hello”); 产生两个对象,堆、池各一个
(由以上可知,因为产生了对象。可以直接用“字符串名.方法()”来调用方法)
4.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 indexOf(String str, int fromIndex),从fromIndex下标开始查找。 -
public int lastIndexOf(String str):查找字符串在当前字符串中最后一次出现的下标索引
-
public String trim():去掉字符串前后的空格
-
public String toUpperCase():将小写转成大写
public String toLowerCase():将大写转成小写 -
public boolean endsWith(String str):判断字符串是否以str结尾
public boolean starsWith(String str):判断字符串是否以str开头 -
public String replace(char oldChar, char newChar):将旧字符串替换成新字符串
-
public String[] split(String str):根据str做拆分,str可以是空格,如split(" “)。str可以是空格或逗号,如split(”[ ,]")。如果要将一个或多个空格或括号作为str,则酱紫写split("[ ,]+")
-
public boolean equals(Object anObject):用于比较两个字符串的内容是否相等
-
public boolean equalsIgnoreCase(String anotherString):用于将字符串与指定的对象比较,不考虑大小写
-
public int compareTo(String
anotherString):如果字符串的第一个字符和参数字符串的第一个字符不等,结束比较,返回两字符的ASCII码差值。如果字符串的第一个字符和参数字符串的第一个字符相等,则以两者的第二个字符做比较,以此类推,直至不等为止,返回该字符的ASCII码差值。
如果两个字符串不一样长,可对应字符又完全一样,则返回两个字符串的长度差值。
String str1 = "abc";String str2 = "aycccc";String str3 = "abc123";int result = str1.compareTo( str2 );sout(result);//-23result = str2.compareTo( str3 );sout(result);//23result = str3.compareTo( str1 );sout(result);//3
4.2 可变字符串
- StringBuffer : 可变长字符串,运行效率慢、线程安全
- StringBuilder : 可变长字符串,运行快、线程不安全
上面两者效率都比String高且节省内存。
psvm(String[] args){// StringBuffer 和 StringBuilder 用法一致StringBuffer sb = new StringBuffer();//StringBuilder sb = new StringBuilder();sb.append("java no1");// 1. append(); 在最后面追加sb.insert(0, "内容xx"); // 2. insert(); 插入内容sb.replace(0, 9, str); // 3.replace(); 替换(区间左闭右开)[0,9)sb.delete(0, 5); // 4. delete(); 删除(左闭右开)[0,5)sb.delete(0, sb.length()); // 5. 清空
}
5 BigDecimal类
很多实际应用中需要用到精确运算,而double是近似值存储,不符合要求。需要用到BigDecimal。
位置:java.math包中
作用:精确计算浮点数
创建方式:BigDecimal bd = new BigDecimal(“x.xxx…”);(建议选择字符串类型)
- 加:BigDecimal add(BigDecimal bd)
- 减:BigDecimal subtract(BigDecimal bd)
- 乘:BigDecimal multiply(BigDecimal bd)
- 除法:divide(BigDecimal bd, int scal, RoundingMode mode)
参数scal:指定精确到小数点后几位
参数mode:指定小数部分的取舍模式,四舍五入模式为RoundingMode.HALF_UP
例如:
BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("0.9");
// 减法
BigDecimal r1 = bd1.subtract(bd2);
sout(r1); // 0.1
BigDecimal r = new BigDecimal("14").subtract(new BigDecimal("4")).divide(new BigDecimal("3"), 3,RoundingMode.HALF_UP);
//sout(r) 3.333
//(14-4)÷3,保留三位小数,使用四舍五入取舍
6 时间类型
6.1 Date类
Date表示特定的瞬间,精确到毫秒。Date类中的大部分方法都已经被Calendar类中的方法所取代
时间单位:1s = 1,000ms = 1,000,000 μs = 1,000,000,000 = ns
psvm(String[] args){// 1 创建Date对象Date date1 = new Date();sout(date1.toString()); //WED Sept 02 22:25:23 CST 2020sout(date1.toLocaleString()); // 已过时,但也能用 2020-9-2// 创建昨天的Date date2 = new Date(date1.getTime() - (60*60*24*1000));sout(date2.toLocaleString());// 2 方法after beforeboolean b1 = date.after(date2);sout(b1); //trueboolean b2 = date1.before(date2);sout(b2); //false// 比较compareTo();int d = date1.compareTo(date2);sout(d); // 比较两个日期的顺序。date1比date2大则为正,否则负// 比较是否相等 equals()boolean b3 = date1.equals(date2);sout(b3); // false
}
6.2 Calendar类
- Calendar提供了获取或设置各种日历字段的方法
- 构造方法 protected Calendar(); 由于是protected 所以无法直接创建
其他方法:
方法名 | 说明 |
---|---|
static Calendar getInstance() | 使用默认时区和区域获取日历 |
void set(int year, int month, int date, int hourofday, int minute, int second) | 设置日历的年、月、日、时、分、秒 |
int get(int field) | 返回给定日历字段的值。字段比如年、月、日 |
void setTime(Date date) | 用给定的date设置此日历时间 |
Date getTime() | 返回一个date表示此日历的时间 |
void add(int field, int amount) | 按照日历的规则,给指定字段添加或减少时间量 |
long getTimeInMilles() | 毫秒为单位返回该日历的时间值 |
例子:
psvm(String[] args){// 1. 创建 Calendar 对象Calendar calendar = Calendar.getInstance();sout(calendar.getTime().toLocaleString());// 2. 获取时间信息// 获取年int year = calendar.get(Calendar.YEAR);// 获取月 从 0 - 11int month = calendar.get(Calendar.MONTH);// 日int month = calendar.get(Calendar.DAY_OF_MONTH);// 小时int hour = calendar.get(Calendar.HOUR_OF_DAY);// 分钟int minute = calendar.get(Calendar.MINUTE);// 秒int second = calendar.get(Calendar.SECOND);// 3. 修改时间Calendar calendar2 = Calendar.getInstance();calendar2.set(Calendar.DAY_OF_MONTH, x);// 4. add修改时间calendar2.add(Calendar.HOUR, x); // x为正就加 负就减// 5. 补充方法int max = calendar2.getActualMaximum(Calendar.DAY_OF_MONTH);// 月数最大天数int min = calendar2.getActualMinimum(Calendar.DAY_OF_MONTH);
}
6.3 SimpleDateFormat类
- SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类
常用的时间模式字母:
字母 | 日期或时间 | 示例 |
---|---|---|
y | 年 | 2019 |
M | 年中月份 | 08 |
d | 月中天数 | 10 |
H | 一天中小时(0-23) | 22 |
m | 分钟 | 16 |
s | 秒 | 59 |
S | 毫秒 | 356 |
psvm(String[] args) throws ParseException{// 1. 创建对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");// 2. 创建DateDate date = new Date();// 格式化date(日期转成字符串)String str = sdf.format(date);sout(str);// 解析(字符串转成时间)Date date2 = sdf.parse("1948/03/12");//必须要与SimpleDateFormat()定义的格式一致sout(date2);
}
6.4 System类
主要用于获取系统的属性数据和其他操作,构造方法私有的
方法名 | 说明 |
---|---|
static void arraycopy(…) | 复制数组 |
static long currentTimeMillis(); | 获取当前系统时间,返回毫秒值 |
static void gc(); | 建议jvm赶快启动垃圾回收期器回收垃圾 |
static void exit(int status); | 退出jvm 如果参数是0表示正常退出jvm 非0表示异常退出 |
//arraycopy 数组复制//src 源数组 //srcPos 从哪个位置开始复制0 //dest 目标数组 //destPos 目标数组的粘贴的开始位置 //length 复制的长度int[] arr = {20, 18, 39, 3};int[] dest = new int [4];System.arraycopy(arr, 0, dest, 1, 2);for (int s:dest) {System.out.println(s);// 输出:0 20 18 0}
}
Arrays.copyOf(original, newLength)也可以复制数组,但这个的源码其实还是用了System类的arraycopy方法
currentTimeMillis()方法的一个应用:获取程序运行用时
long start = System.currentTimeMillis();//{程序}long end = System.currentTimeMillis();sout("用时:"+(end-start));
System.exit(0);//下面的代码不再执行,因为JVM已经退出