1.内部类(了解的格式)
分类有哪些?
成员内部类、局部内部类
成员内部类:类中,方法外
特点:可以访问外部类成员(包括私有成员)
直接去访问外部类的中的成员内部类的成员方法:(成员内部类没有privata和static修饰)
外部类名.内部类名 对象名 = new 外部类名().内部类名();
//外部类
class Outer2{
//成员变量
public int num = 20 ;
private int num2 = 50 ;
//成员内部类
class Inner2{
//成员方法
public void show(){
System.out.println(num) ;
System.out.println(num2) ;
}
}
//外部类的成员方法
public void method(){
// show() ; Outer2自己的show方法
//访问成员内部类的成员方法
//创建Inner2类对象
Inner2 in = new Inner2() ;
in.show() ;
}
}
//测试类
public class InnerClassDemo2 {
public static void main(String[] args) {
//创建外部类对象
//访问外部类的成员方法,间接的调用了成员内部类的成员方法
Outer2 ou = new Outer2() ;
ou.method() ;
System.out.println("--------------------------------------------------") ;
//测试类中:想直接去访问外部类里面的成员内部类的show
//外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
Outer2.Inner2 oi = new Outer2().new Inner2() ;
oi.show() ;
}
}
局部内部类:在方法定义中定义的类
特点:可以访问外部类成员(包括私有成员)
内部类的成员安全,加入private,
成员内部类可以使用过static修饰
使用static修饰的特点:
静态成员内部类里面的所有成员方法,访问外部类成员必须先为静态
直接访问静态的成员内部类的成员方法:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
package com.qf.innerclass_01;
/**
* 成员内部类所涉及到的修饰符的问题:
* 有的时候不想让外部类直接去访问内部类的成员,为了保证内部类的成员安全,加入private
* 举例:
* 人有身体,身体有心脏;
* 伪代码
* class Body{
* //身体内有心脏
* //为了保证安全性,加入private修饰
* private class Heart{
* //成员方法
* public void operator(){
* System.out.println("心脏搭桥") ;
* }
* }
*
* //外部类的成员方法
* public void method(){
* if(你是外科医生){
* //创建Heart对象,去调用operator方法
* }
* }
*
*
* }
*
*
* //直接访问成员内部类中的operator方法
* 外部类名.内部类名 对象名 = new 外部类名().new 内部类名() ;
* Body.Heart bh = new Body().new Heart() ;会报错的
*
*
* 成员内部类可以使用过static修饰:
* 特点:静态的成员内部类它里面的所有 成员方法:
* 无论是静态的方法还是非静态的,访问外部类的成员:必须先为静态
*
* 想直接去访问静态的成员内部类的这些成员方法:??
*
* 外部类名.内部类名 对象名 = new 外部类名.内部类名();
*
*/
//外部类
class Outer3{
private int num = 100;
public static int num2 = 20 ;
//静态修饰
static class Inner3{ //Inner3现在看成是外部类的静态成员!
//非静态的方法
public void show(){
// System.out.println(num) ;
System.out.println(num2) ;
System.out.println("show Inner3");
}
//静态的方法
public static void show2(){
System.out.println(num2) ;
//System.out.println(num) ;
System.out.println("show2 Inner3");
}
}
}
//测试类
public class InnerClassDemo3 {
public static void main(String[] args) {
//访问成员内部类的成员方法
//外部类名.内部类名 对象名 = new 外部类().new 内部类名() ;
//Outer3.Inner3 oi = new Outer3().new Inner3() ; 用不了,只能针对非静态的成员内部类!
//针对静态的成员内部类:直接去访问里面的成员方法
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer3.Inner3 oi = new Outer3.Inner3() ;//Inner3类看成是Outer3的静态成员
oi.show() ;
oi.show2() ;
System.out.println("----------------------------------------");
//show2()是静态的成员内部类的静态成员
Outer3.Inner3.show2();
}
}
面试题:
控制台打印 30 20 10
class Outer2{
int num = 10 ;
//成员内部类
class Inner2{
int num = 20 ;
public void show(){
int num = 30 ;
//补全代码
System.out.println(num) ; //就近原则
System.out.println(this.num) ; //访问本类的成员变量
// System.out.println(new Outer2().num) ; //创建外部类对象.变量名
//this:代表当前类---->Outer2.this--->外部类的this限定(访问的是外部类中的信息)
System.out.println(Outer2.this.num);
}
}
}
//测试类
public class InnerClassDemo2 {
public static void main(String[] args) {
Outer2.Inner2 oi = new Outer2().new Inner2() ;
oi.show();
}
}
局部内部类里面的成员在访问局部变量的时候,局部变量有什么要求?
局部内部类里面的成员在访问局部变量的时候,局部变量有什么要求?
JDK8以前的版本,局部内部类在访问外部类的成员方法中的局部变量的时候,此时局部变量必须加入final修饰!
原因:
局部变量的生命周期随着方法调用而存在,随着方法调用结束而消失;
外部类的成员方法调用完毕,此时这个局部变量应该释放了,但是当前这个成员方法中创建局部内部类对象
使用局部内部类对象访问它里面的成员方法,成员方法还在使用这个局部变量,所以此时这个变量为常量,显示的加入final修饰
JDK8以及jdk8以后:优化了
可以通过反编译工具---->自动加入final,还是定义一个常量
2.内部类的一种简写:针对接口/抽象类:匿名内部类(重点)
匿名内部类:是内部类的一种简化格式
针对抽象类或者接口去使用
匿名的格式
new 类名/接口名(){
重写方法;
};
应用范围:在局部位置中使用
匿名内部类的本质:
是继承该抽象类或者实现接口的对象
//定义接口
interface Inter{
void show() ;
void show2() ;
}
//正常有一个接口的实现类
/*class InterImpl implements Inter{ //有名字的子实现类
@Override
public void show() {
System.out.println("show Inter...");
}
}
//在测试类中测试子实现类
Inter inter = new InterImpl() ;
inter.show();
*/
//Outer类
class Outer{
//外部类的成员方法
public void method(){
/**
* new 类名(抽象类)或者接口名(){
* 重写类里面或者接口的抽象功能!
* } ;
*/
//优化:给匿名内部类----起一个名字,使用对象名来访问
Inter inter = new Inter() {
@Override
public void show() {
System.out.println("show Inter");
}
@Override
public void show2() {
System.out.println("show2 Inter");
}
} ;
inter.show();
inter.show2();
}
}
//测试类
public class InnerClassDemo {
public static void main(String[] args) {
Outer outer = new Outer() ;
outer.method() ;
}
}
package com.qf.return_05;
/**
* 匿名内部类开发中使用场景2:
* 方法返回值是抽象类或者接口
*/
interface Love{
void love() ;
}
//LoveDemo
class LoveDemo{
public Love method(){ //返回是一个接口:返回接口的子实现类对象
//?如何返回
//接口不能new
//接口多态
//2使用接口的匿名内部类
/**
* new 类名或者接口(){
* //重写方法
* }
*/
return new Love() {
@Override
public void love() {
System.out.println("爱生活,爱Java,爱高圆圆!");
}
};
}
}
//定义一个子实现类
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love life,love 高圆圆");
}
}
//测试类
public class ReturnDemo {
public static void main(String[] args) {
LoveDemo ld = new LoveDemo() ;
Love love = ld.method(); //使用的接口匿名内部类的子实现类对象!
love.love();
}
}