Java学习笔记--第二周
一、 final
用法:
1、修饰一个类(一个类被final修饰后就不能被其他类继承了,但对其内容没有影响)(此类也叫做太监类)
public final class 类名称{
//......
}
2、修饰一个方法(此方法将作为最终方法,不能覆盖重写,因此abstract和final不能写在一起)
修饰符 final 返回值类型 方法名(参数列表){
//......
}
3、修饰局部变量
- final修饰基本类型变量
只能输入一次,之后值就不能改变了。
public class Method{
public static void main(String[] args){
final int num=10;
//num=20; 错误 final修饰后只能输入一次
//也可以这样,但是之后值就不能改变了
final int num1;
num = 20;
}
}
- final修饰引用类型变量
引用类型变量指向的是一个地址,因此用final修饰引用类型的变量,其地址值不可变,所以不能对同一个变量new新值或将另一变量赋值给该变量。但是可以对引用类型的值进行修改(通过类中的方法修改)。
4、修饰成员变量
成员变量有默认值,局部变量没有默认值,因此成员变量必须赋值(可以手动赋值,也可以通过构造方法赋值,二者选其一)
二、权限修饰符
定义一个类时,权限修饰符的使用规则:
外部类:public或(default)
成员内部类:public、protected、(default)或private
局部内部类:什么都不能写。 注意,这里没写不是代表是default
class 类名称 {
//......
}
三、内部类
顾名思义,就是在一个类中再写一个类。有成员内部类、局部内部类(包含匿名内部类)两种,但匿名内部类用的比较多,故单独列出来讲解。
1、成员内部类
修饰符 class 外部类名称{
修饰符 class 内部类名称{
//......
}
//......
}
内部用外部变量或方法,可以随意访问;
而外部用内部,则需要内部类对象。
1、成员内部类访问方法:
- 直接访问
外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();
//这样就创建了一个内部类对象
public class Method{
public static void main(String[] args) {
Wo.M xy=new Wo().new M();
//注意这里的写法
System.out.println(xy.x);// 1
xy.Me();// 内部类方法实现了
}
}
class Wo {
//成员内部类
public class M{
int x=1;
public void Me(){
System.out.println("内部类方法实现了");
}
}
}
- 间接访问
在外部类中定义使用内部类,再在main方法中使用外部类的方法。
附:重名变量的处理方法:
在内部类中访问外部类的变量:外部类.this.变量名(无论是在内部类中,还是在内部类方法中都这样写),如果不重名,则可以直接使用变量名。
2、局部内部类
与成员内部类的使用方法一样,不过需要注意的是:如果局部内部类要使用方法中的变量,那么变量的值不能改变(必须使用final修饰,java 8之后可以不用写final,但值不能变。保险起见,写上准没错。)
3、匿名内部类
是局部内部类的一种。一般写在main方法中
//接口名称 对象名 = new 接口名称(){......};
//{......}是匿名内部类
My my=new My(){
@Override
public void p() {
System.out.println("p");
}
};
my.p();
//这里不一定只能写接口名称,也可以写其他类。只是常用接口
注意事项:
- 一个匿名内部类只能创建一个对象
- 也可以省略对象名直接点方法
new My(){
@Override
public void p() {
System.out.println("p");
}
}.p();
//这样写只能用一次
- 匿名对象和匿名内部类不是一回事
附:
1、类作为成员变量类型
2、接口作为成员变量类型
3、接口作为方法的参数或返回值
四、常用API(二)
1、Object类
Object类是所有类的父类(又名超类)。所有类都继承Object类。既然Object是父类,那么子类就可以用父类的方法。这里介绍toString和equals两种常用的方法。
(一)toString
将对象返回成字符串。在默认情况下,会返回对象的地址值,就像直接打印对象名,这样做的意义不大。因此toString需要重写才能用。
package practice;
public class Method {
public static void main(String[] args) {
Me me=new Me();//Me为一个含有String name和int age的标准类
me.setName("肖");
me.setAge(21);
System.out.println(me); //practice.Me@7ef20235
System.out.println(me.toString()); //practice.Me@7ef20235
//这里的me和me.toString()是等价的
}
}
重写因写法不同而返回不同,可以用编译器默认重写,也可以自己安排(这里以IntelliJ IDEA 为准)
-
编译器默认重写
Code—>Generate—>toString(),再全选就可以了 -
自定义 (与编译器默认重写几乎一模一样,就是返回值改成自己想要的就行)如:
@Override
public String toString() {
return "["+name+","+age+"]";
}
// 这样写的话,上述返回值就会变成[肖,21]
(二)equals
比较两个对象是否相等,返回值是布尔值。
在不重写的情况,equals比较的是两个对象的地址值是否相等,这样是没有意义的,因此进行比较就必须重写。值得注意的是Object中的源代码是这样的:
public boolean equals(Object obj){
return (this==obj);
}
不难看出参数列表是Object类,是父类。一旦重写就变成了多态,会访问出错(父类不能访问子类的变量和方法)。
需要进行强转
//自己写(仅供理解)
@Override
public boolean equals(Object obj){
if (obj==null||this==obj)return false;
if (obj instanceof Me){
Me me=(Me)obj;
boolean b=(this.name==me.name&&this.age==me.age);
return b;
}
return false;
}
}
//编译器写
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Me me = (Me) o;
return age == me.age &&
Objects.equals(name, me.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
附:Objects类的equals
Objects类是java 7之后提供的一个静态类(容忍空指针异常)用法如下:
package practice;
import java.util.Objects;
public class Method {
public static void main(String[] args) {
Me me=new Me("许");
Me me1=new Me("小");
System.out.println(Objects.equals(me,me1));//false
}
}
2、日期和时间
(一)Date
Date是表示时间和日期的类
毫秒值(long类型):现在时间到时间原点(1970/1/1 00:00:00)的毫秒值
作用:可以计算时间差。
获取毫秒值的方法:
//通系统方法获取
System.out.println(System.currentTimeMilliis());
//通过Date方法获取
Date date=new Date();
System.out.println(date.getTime());
//Date的有参获取日期
Date date=new Date(/*毫秒值*/L);
通过Date类显示日期和时间:
Date date=new Date();
System.out.println(date);
(二)DateFormat
是日期/时间格式化子类的抽象类
- 格式化(日期—>文本)
- 解析(文本—>日期)
SipmleDateFormat是DateFormat类的子类,常用的方法有:
String format(Date date)
Date parse(String parttern)
用法:
SipmleDateFormat sip=new SipmleDateFormat("yyyy/MM/dd HH点mm分钟ss秒");
/*
这里需要先输入一个格式,程序会按照这个格式输出
年(y) 月(M) 日(d) 时(H) 分(m) 秒(s)
*/
Date date=new Date();
String str=sip.format(date);//将日期转换成文本 2021/03/29 09点46分26秒
parse方法将文本转换成日期
注意:parse会转换异常,因此需要在main方法后写上throws ParseException
(三)Calender
日历类(也是一个抽象类),是在Date类之后出现的,替换了许多Date类中的方法,可以显示年月日等时间。
//常用getInstance方法返回一个Calendar的对象
Calendar calendar=Calendar.getInstance();
//getInstance是Calendar类的一个静态方法
System.out.println(calendar);
四种常用方法:
public int get(int field);返回给定日历字段的值
public void set(int field,int value);//将给定日历段设置成给定值
public abstract void add(int field,int account);//增加或减少给定日历字段的时间值
public Date getTime();//转换成Date类型
//日历字段:YEAR、 MONTH、DATE、HOUR、MINUTE、SECOND
Calendar c=Calendar.getInstance();
int x = c.get(Calendar.YEAR);//一次只能返回一个日历字段
System.out.println(x);//2021
c.set(Calendar.YEAR,2020);
System.out.println(c.get(Calendar.YEAR));//2020
//set方法可以重载,如下所示:
c.set(2020,3,16);
System.out.println(c.get(Calendar.MONTH));//3
c.add(Calendar.YEAR,2);
System.out.println(c.get(Calendar.YEAR));//2023
c.add(Calendar.YEAR,-2);
System.out.println(c.get(Calendar.YEAR));//2021
Date date=c.getTime();
System.out.println(date);//Sun Apr 04 14:52:45 CST 2021
3、System
在java.long.System中,提供了大量静态方法,可以获取系统相关的信息或系统级操作。
public long currentTimeMillis() 返回以毫秒为单位的当前时间
可以用于判断一个程序的快慢
long begin=System.currentTimeMillis();
for (int i=1;i<=9999;i++){
System.out.println(i);
}
long end=System.currentTimeMillis();
System.out.println("用时"+(end-begin)+"毫秒");//用时113毫秒
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量。
int[] x={1,2,3,4,5,6};
int[] y={4,5,6,7,8,9};
System.out.println(Arrays.toString(y));//[4, 5, 6, 7, 8, 9]
System.arraycopy(x,0,y,0,3);
System.out.println(Arrays.toString(y));//[1, 2, 3, 7, 8, 9]
4、StringBuilder
字符串缓存区,支持可变字符串,提高字符串的效率
构造方法分有参和无参,常用方法有:
public BtringBuilder append(o)(o为任意类型数据)
作用:增加字符串的长度
public String toString()
作用:将StringBuilder类型转换成String类型
转换:
- StringBuilder–>String:toString方法
- String–>StringBuilder:有参构造
//无参
StringBuilder b=new StringBuilder();
//有参
StringBuilder b=new StringBuilder("abc");