Java 内部类
成员内部类在一个类中定义了另一个类,则将定义在类中的那个类称之为成员内部类。成员内部类也是最普通的内部类。成员内部类可直接访问外部类(使用:外部类.this.xxx);外部成员类要访问内部类,必须先建立成员内部类对象;成员内部类可使用任意作用域修饰(public、protected、默认、private);成员内部类可访问外部类任何作用域修饰的属性和方法;外部类建立成员内部类对象之后,可以访问任何作用域修饰的内部类属性和方法。静态成员内部类在一个类中定义了另一个 static 类,则将定义在类中的那个 static 类称之为静态成员内部类。静态成员内部类也就是给内部成员类加上 static 修饰符。不能从静态成员内部类中访问非静态外部类对象。局部内部类一个类定义在另一个类的局部(方法或者任意作用域),这个类就称之为局部内部类。局部内部类不能使用任何访问修饰符;局部类如果在方法中,可以直接使用方法中的变量,不需要通过OutClass.this.xxx的方式获得。匿名内部类没有名字的内部类就叫做匿名内部类。匿名内部类必须继承一个父类或者实现一个接口匿名内部类不能定义任何静态成员和方法匿名内部类中的方法不能是抽象的相关面试题
1.Java 中的内部类有哪些? 答:内部类包含以下 4 种:
静态内部类:static class StaticInnerClass{}; 成员内部类:private class InstanceInnerClass{}; 局部内部类:定义在方法或者表达式内部; 匿名内部类:(new Thread(){}).start()。 2.以下关于匿名内部类说法错误的是? A:匿名内部类必须继承一个父类或者实现一个接口 B:匿名内部类中的方法不能是抽象的 C:匿名内部类可以实现接口的部分抽象方法 D:匿名内部类不能定义任何静态成员和方法
答:C 题目解析:匿名内部类规定必须实现接口的所有抽象方法,否则程序会报错
相关面试题
Java 中的内部类有哪些?
答:内部类包含以下 4 种:
静态内部类:static class StaticInnerClass{}; 成员内部类:private class InstanceInnerClass{}; 局部内部类:定义在方法或者表达式内部; 匿名内部类:(new Thread(){}).start()。
以下关于匿名内部类说法错误的是?
A:匿名内部类必须继承一个父类或者实现一个接口B:匿名内部类中的方法不能是抽象的C:匿名内部类可以实现接口的部分抽象方法D:匿名内部类不能定义任何静态成员和方法答:C 题目解析:匿名内部类规定必须实现接口的所有抽象方法,否则程序会报错
成员内部类和局部内部类有什么区别?
答:内部成员类和局部内部类的区别如下:
内部成员类可以使用任意访问修饰符,局部内部类不能使用任何访问修饰符;局部内部类是声明在外部类的方法或其他作用域范围内的,内部类是直接声明在外部类之中的,与方法和属性平级。为什么要使用内部类?内部类的使用场景有哪些?
使用内部类的好处有以下两个:
可以作为多继承的一种实现方式,最早内部类的实现就是平衡 Java 语言中没有多继承的一种方式;方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。 内部类可以作为多继承的一种实现方式进行使用,因为每个内部类都能独立的继承一个类或接口,所以整个类就可以实现多继承。Java 时间操作
获取时间
Datedate = newDate();System.out.println(date);Calendar calendar = Calendar.getInstance();Datetime = calendar.getTime();System.out.println(time);
JDK8
// 获取日期LocalDate localDate = LocalDate.now();System.out.println(localDate);// 获取时间LocalTime localTime = LocalTime.now();System.out.println(localTime);// 获取日期和时间LocalDateTime localDateTime = LocalDateTime.now();System.out.println(localDateTime);
获取时间戳
long ts = newDate().getTime();System.out.println(ts);long ts2 = System.currentTimeMillis();System.out.println(ts2);long ts3 = Calendar.getInstance().getTimeInMillis();System.out.println(ts3);
JDK8
// 获取当前时间戳(精确到毫秒)long second = Instant.now().getEpochSecond();long milli = Instant.now().toEpochMilli();// 获取当前时间戳(精确到秒)
格式化时间
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sf.format(newDate()));
JDK8
DateTimeFormatter 是线程安全的
// 时间格式化①DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String timeFormat = dateTimeFormatter.format(LocalDateTime.now());System.out.println(timeFormat); // 时间格式化②String timeFormat2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
JDK 8 对时间操作新增了三个类:LocalDateTime、LocalDate、LocalTime。 LocalDate 只包含日期,不包含时间,不可变类,且线程安全。 LocalTime 只包含时间,不包含日期,不可变类,且线程安全。 LocalDateTime 既包含了时间又包含了日期,不可变类,且线程安全。
怎么保证 SimpleDateFormat 的线程安全?
保证 SimpleDateFormat 线程安全的方式如下:
使用 Synchronized,在需要时间格式化的操作使用 Synchronized 关键字进行包装,保证线程堵塞格式化;手动加锁,把需要格式化时间的代码,写到加锁部分,相对 Synchronized 来说,编码效率更低,性能略好,代码风险较大(风险在于不要忘记在操作的最后,手动释放锁);使用 JDK 8 的 DateTimeFormatter 替代 SimpleDateFormat。