Java之路 - final、内部类、Object、Date、Calendar
2021-02-15 20:21
标签:指针 就是 复制 设置 value sed err mount date final表示最终的、不可变的,对于类和方法来说,abstract 和 final 关键字不能同时使用,因为前者是必须要覆盖重写,后者是不能覆盖重写,自相矛盾 (1)可以用来修饰一个类 (2)可以用来修饰一个方法 (3)可以用来修饰一个局部变量 (4)还可以用来修饰一个成员变量 对于引用类型来说,不可改变说的是变量当中的地址值不可改变 情况: Calendar calendar = Calendar.getInstance(); //多态 (4)public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象 把日历对象转为日期对象 Java之路 - final、内部类、Object、Date、Calendar 标签:指针 就是 复制 设置 value sed err mount date 原文地址:https://www.cnblogs.com/caixiaowu/p/12696189.html1.final的用法
第一种用法: - - 用于修饰类
格式: public final class 类名称
含义:当前这个类不能有任何子类(太监类)
第二种用法: - - 用于修饰方法,这个方法就是最终方法,不能被覆盖重写
格式:修饰符 final 返回值类型 方法名称(){ 方法体 }
第三种用法:- - 用于修饰局部变量
格式:final 数据类型 名称 = 数值; 一但使用final对局部变量进行限制,那么这个变量终生不可改变
什么叫不可变?:对于基本数据类型来说,不可变说的是变量当中的数据不可改变
类Myclas:
public class MyClass {
private String name;
public MyClass() {
}
public MyClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
执行类:
public class MyDemoFinal {
public static void main(String[] args) {
final int num = 100; //此时num不可改变了
MyClass c1 = new MyClass("chris");
System.out.println(c1.getName());
System.out.println(c1);
c1 = new MyClass("joe");
System.out.println(c1.getName());
System.out.println(c1);
}
}
此时案例中c1的地址值是发生了改变的
如果在c1之前加入final,地址值就不可改变了
final MyClass c1 = new MyClass("chris");
c1 = new MyClass("joe"); //!!!!错误写法
c1.setName("joe"); //这种是可行的 对其内容是可以改变 第四种用法: - -用于修饰成员变量
(1)由于成员变量具有默认值,所以用了final之后必须手动赋值,才不会给默认值
(2)对于final的成员变量,要么使用直接赋值
(3)要么通过构造方法赋值,必须保证所有重载形式的构造方法都对其进行了赋值,且去掉setter方法
public class MyClass {
private final String name;
public MyClass() {
name = "chris";
}
public MyClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
2.Java中四种权限修饰符
(1)public > (2)protected > (3)(default) > (4)private
同一个类(我自己) (1)yes (2) yes (3)yes (4)yes
同一个包(我邻居) (1)yes (2) yes (3)yes (4)no
不同包子类(我儿子) (1)yes (2) yes (3)no (4)no
不同包非子类(陌生人)(1)yes (2) no (3)no (4)no
3.内部类(一个类内部包含另个类) 里面的就是内部类
分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
4.成员内部类
格式: 修饰符 class 外部类名称 {
修饰符 class 内部类名称{
//.....
}
//...
}
注意事项:内用外,随意访问; 外用内,需要内部类对象
如何使用成员内部类?有两种方式:
(1)间接方式:在外部类的方法当中,使用内部类;然后main方法调用外部类的方法
外内部类
public class Body {
//内部类
public class heart{
public void methodHeart(){
System.out.println("内部类方法");
System.out.println("我叫" + name); // 可以访问外部的成员变量
}
}
//外部类的成员变量
private String name;
public void methodBody(){
System.out.println("外部类方法");
heart heart = new heart();
heart.methodHeart();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
main:
public class MyDemoFinal {
public static void main(String[] args) {
Body body = new Body();
body.methodBody();//通过调用外部类方法使用内部类方法
}
}
(2)直接方式:公式: 外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
public class MyDemoFinal {
public static void main(String[] args) {
Body body = new Body();
body.methodBody();//通过调用外部类方法使用内部类方法
//直接访问成员内部类
Body.heart directUse = new Body().new heart();
directUse.methodHeart();
}
}
内外部类变量重名时的使用方法:
public class Outer {
int num = 10; //外部类成员变量
public class Inner{
int num = 20; //内部类成员变量
public void methodInner(){
int num = 30; //内部类方法的局部变量
System.out.println(num); //输出的是局部变量
System.out.println(this.num); //输出的是内部类成员变量
System.out.println(Outer.this.num);//外部类的成员变量
}
}
}
5.局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类,只要当前所属的方法才能使用它,出了这个方法外面就不能用了
定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//....
}
}
}
示例:
public class Outer {
public void methodOuter(){
class Inner { //这是个局部内部类
int num = 10;
public void methodInner(){
System.out.println(num);
}
}
Inner in = new Inner();
in.methodInner();
}
}
局部内部类如果希望访问所在方法的局部变量,那么这个变量必须是有效【final】的,从java8开始,只要局部变量事实不变,既不被改变,那么final关键字可以省略 - - - 和生命周期有关
public class Outer {
public void methodOuter(){
int num = 10;
class Inner { //这是个局部内部类
public void methodInner(){
System.out.println(num);
}
}
}
}
原因:(1)new出来的Inner对象在堆内存当中,
(2)而局部变量num是跟着方法走的,在栈内存当中
(3)methodOuter方法运行结束之后,立刻出栈,局部变量就会立刻消失
(4)但new出来的对象Inner会在堆当中持续存在,直到垃圾回收消失
(5)所以这个num只要保证不会变,既有效final,那么它就会被复制到常量池中,这就解决了生命周期的问题
6.定义一个类时,权限修饰符的规则
(1)外部类:public / (default)
(2)成员内部类:public / protected / (default) / private
(3)局部内部类:什么都不能写
7.匿名内部类 重点
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】
定义格式:
接口名称 对象名 = new 接口名称 {
这里面覆盖重写所有抽象方法
};
注意事项:
(1)匿名内部类在创建对象的时候,只能使用唯一一次,如果想再new,必须再重写方法
(2)匿名对象无法调用第二次方法
匿名内部类的匿名对象用法
new MyInterface() {
@Override
public void methodAbs1() {
System.out.println("1111");
}
@Override
public void methodAbs2() {
System.out.println("2222");
}
}.methodAbs1();
(3)匿名内部类是省略了【实现类/子类】,但是匿名对象是省略了【对象名称】
8.Object类
类Object是类层次结构的根(最顶层)类,每个类都使用Object作为超(父)类
(1)Object类 的 toString方法 默认打印的是对象的地址值
直接打印对象的名字,其实就是调用对象的toString方法
public class DemoOtherClass {
public static void main(String[] args) {
Person p = new Person("chris",21);
String s = p.toString();
System.out.println(s);
System.out.println(p);
}
}
因此这样打印没有什么意义,我们要在定义的类中重写toString方法
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name=‘" + name + ‘\‘‘ +
", age=" + age +
‘}‘;
}
(2)Object类 的 equals方法 指示其他某个对象是否与此对象‘相等’
Object类中equals方法的源码:
public boolean equals(Object obj) {
return (this == obj);
}
参数为引用类型时,比较的是双方的地址值
public class DemoOtherClass {
public static void main(String[] args) {
Person p1 = new Person("chris",21);
Person p2 = new Person("joe",20);
boolean result = p1.equals(p2);
System.out.println(result);
System.out.println(p1.equals(p2));
}
}
我们可以重写equals方法来判断两个对象的属性是否一致,以后用快捷键添加就好了
因为equals接收的是Object类型,所以此处隐含着一个多态 Object obj = p1 = new Person("chris",21)
我们又知道多态有一个弊端:无法使用子类特有的属性和方法 因此此时要使用向下转型进行强转
重写的equals方法:
@Override
public boolean equals(Object obj){
//增加一个判断,如果传过来的参数obj是this本身,直接返回true
if(obj == this){
return true;
}
//增加一个判断,如果传过来的参数为null,直接返回false,提高程序的效率
if (obj == null){
return false;
}
//先增加一个判断,判断obj是否是person类型才能转换,比如random,可以防止ClassCastException
if (obj instanceof Person){
//使用向下转型
Person p = (Person) obj;
//比较两个对象的属性;一个是调用方法的this(p1),一个是p(obj=p2) 此时在使用字符串方法中的equals方法来比较
boolean b = this.name.equals(p.name) && this.age == p.age;
return b;
}
//不是Person类型,就直接返回false
return false;
}
9.Objects类
Objects类的提供的equals方法是静态方法,通过类直接调用,可以防止空指针异常
源码:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
10.Date类 表示特定的瞬间,精确到毫秒(long类型)
毫秒:千分之一秒 1000毫秒 = 1 秒
特定的瞬间:一个时间点,一刹那的时间 2020-04-16 11:04:24:333 这就是一个瞬间
毫秒值的作用:可以对时间和日期进行计算
如:在对2044-02-03 到 2050-05-22 号之间有多少天 可以将日期转换为毫秒(就是计算当前日期到时间原点之间一共经历了多少毫秒),计算完后再把毫秒转换为日期
时间原点(0毫秒):1970年1月1日 00:00:00(英国格林威治)
注意:中国属于东八区,会把时间增加8小时
(1)空构造方法 获取当前的时间
public class DemoOtherClass {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis());//获取当前系统时间到时间原点经历了多少毫秒
methodDate();
}
public static void methodDate(){
Date date = new Date();
System.out.println(date);
}
}
(2)带参数的构造方法 long类型表示的就是传递毫秒值,把毫秒转换为Date日期
public static void methodDate(){
Date date1 = new Date();
System.out.println(date1);
Date date2 = new Date(0L);
System.out.println(date2);
}
此时date2的输出值为:Thu Jan 01 08:00:00 CST 1970
(3)成员方法Long getTime() 返回自1970 年 。。。 以来此对象表示的毫秒值 相当于System.currentTimeMillis()
(4)String toLocalString 根据本地格式转换为日期对象
public class CalendarPratise {
public static void main(String[] args) {
Date data = new Date();
System.out.println(data.toLocaleString()); //当前电脑下的时间
}
}
11.DateFormate类 将Date对象转换为String对象 它是一个抽象类,可以用它的子类SimpleDateFormat
它是日期/时间格式化子类的抽象类;
子类SimpleDateFormat的方法:
(1)成员方法 String format(Date date):按照指定的模式,把Date日期,格式化为符合模式的字符串
(2)成员方法 Date parse(String source):把符合模式的字符串解析为Date日期
SimpleDateFormat
构造方法:SimpleDateFormat(String Pattern) 传入模式
参数:传递指定的模式
模式:区分大小写 y - 年 M - 月 d - 日 H - 时 m-分 s - 秒 如:"yyyy-MM-dd HH-mm-ss" 连接符号可以改变
format方法:
private static void demo01() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date data = new Date();
String timeText = sdf.format(data);
System.out.println(data);
System.out.println(timeText); //输出的是按照构造方法中指定的模式的字符串
}
parse方法:将符合构造方法中模式的字符串解析为Date日期
private static void demo01() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date = sdf.parse("2020-04-16 13-28-08");
System.out.println(date);
}
练习:输入出生年月日,获取你已经出生了多少天
public class DatePratise {
public static void main(String[] args) throws ParseException {
Scanner s = new Scanner(System.in);
System.out.println("请输入您的生日,格式为yyyy-MM-dd");
String birthday = s.next();
//将获取的生日解析为Date格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateBirthday = sdf.parse(birthday);
//将Date转换为毫秒值
long seconds = dateBirthday.getTime();
//获取当前的日期转换为毫秒值
Long timeNow = new Date().getTime();
//两个时间相减 now - past
long time = timeNow - seconds;
//将差值转换为天 (s/1000/60/60/24)
System.out.println("你已经出生了" + time/1000/60/60/24 +"天");
}
}
12.Calendar日历类 是一个抽象类 无法直接创建对象使用,里面有一个静态方法getInstance,该方法返回了其子类对象
成员方法:
参数: int field:日历类的字段,可以使用Calendar类的静态成员变量获取
(1)get(int field)方法
通过制定日历字段,返回给定日历字段的值
public class CalendarPratise {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(); //多态
int year = calendar.get(Calendar.YEAR);
System.out.println(year);
int month = calendar.get(Calendar.MONTH);
System.out.println(month); //西方的月份为0-11月 所以我们要加一个月
int date = calendar.get(Calendar.DATE);
System.out.println(date);
}
}
(2)set(int field,int value)方法
将给定的日历字段设置为给定值
public class CalendarPratise {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(); //多态
calendar.set(Calendar.YEAR,2050);
calendar.set(2012,3,4); //重载方法同时对三个值进行设置
}
}
(3)add(int field,int amount)方法
根据日历的规则,为给定的日历字段增加或减少指定的值
public class CalendarPratise {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(); //多态
calendar.add(Calendar.YEAR,2);//将年份增加两年
}
}
public class CalendarPratise {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(); //多态
Date time = calendar.getTime();
System.out.println(time);
}
}
上一篇:java反射的原理,作用
下一篇:C++ auto 的使用
文章标题:Java之路 - final、内部类、Object、Date、Calendar
文章链接:http://soscw.com/index.php/essay/55793.html