一、内部类
1.1、内部类概念
定义在一个类内部中的另一个类,被称为内部类
特点:
可以直接访问,内部类的外部类中的,成员属性和方法(包含-PRivate)
外部类要访问内部类中的成员和方法,需要先建立内部类对象
1.2、示例
packagecom.day08.innerclass.demo1;
/**
* 包含内部类
* @author denny
*
*/
public class Outer { //外部类
//private成员
private String name="张三";
private int age=20;
private String gender="男";
/**
* 内部类
*/
classInner{
private int num=3;
public voidhello(){
System.out.println("姓名:"+name+"年龄:"+age
+"性别:"+gender);
}
public intgetNum() {
returnnum;
}
public void setNum(intnum) {
this.num =num;
}
}
/*
* 外部类中的方法
*/
public voidshow(){
System.out.println("姓名:"+this.name+"年龄:"+this.age
+"性别:"+this.gender);
}
/*
* 调用内部类
*/
public voidsay(){
Inner inner=newInner();
System.out.println("调用内部类:"+"num="+inner.getNum()+", num="+inner.num);
}
publicString getName() {
returnname;
}
public voidsetName(String name) {
this.name =name;
}
public intgetAge() {
returnage;
}
public void setAge(intage) {
this.age =age;
}
publicString getGender() {
returngender;
}
public voidsetGender(String gender) {
this.gender =gender;
}
}
测试外部类
packagecom.day08.innerclass.demo1;
public classOuterTest {
public static voidmain(String[] args) {
//外部类调用内部类
Outer o=newOuter();
o.show();
o.say();
}
}
结果:
姓名:张三年龄:20性别:男
调用内部类:num=3, num=3
测试内部类
packagecom.day08.innerclass.demo1;
public classInnerTest1 {
public static voidmain(String[] args) {
// 声明内部类中对 象,先声明外部类,再声明内部类
Outer.Inner inner = new Outer().newInner();
inner.hello();
}
}
姓名:张三年龄:20性别:男
调用内部类:num=3, num=3
1.3、静态内部类
如果内部类是static修饰的就只能调用父类中static成员
声明方式,可直接外部类.内部类()来声明或者调用
packagecom.day08.innerclass.demo3;
public classOuter {
//private成员
private String name="张三";
static int age=20;
private String gender="男";
/*
* 外部类中的方法
*/
public voidshow(){
System.out.println("姓名:"+this.name+"年龄:"+this.age
+"性别:"+this.gender);
}
/**
* 内部类
*/
static classInner{
private int num=3;
public voidhello(){
System.out.println("外部类年龄:"+age
+",内部类属性"+this.num);
}
}
public static voidmain(String[] args) {
//静态内部类可以直接通过外部类.内部类声明
Outer.Inner inner=newOuter.Inner();
inner.hello();
}
}
外部类年龄:20,内部类属性3
1.4、内部类成员是static的话
这个内部类必须被static修饰,static只能调用外部类和内部类中的stiatic的成员.
packagecom.day08.innerclass.demo3;
public classOuter {
//private成员
private String name="张三";
static int age=20;
private String gender="男";
/*
* 外部类中的方法
*/
public voidshow(){
System.out.println("姓名:"+this.name+"年龄:"+this.age
+"性别:"+this.gender);
}
/**
* 内部类
*/
static classInner{
private static int num=3;
public static voidhello(){
System.out.println("外部类年龄:"+age
+",内部类属性"+num);
}
}
public static voidmain(String[] args) {
//静态内部类m成员也是静态的可以直接调用Outer.Inner.hello();
}
}
结果:外部类年龄:20,内部类属性3
1.5、声明在外部类中成员方法中的内部类
声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰
packagecom.day08.innerclass.demo3;
public classOuter {
// private成员
private String name = "张三";
static int age = 20;
private String gender = "男";
/*
* 外部类中的方法
*/
public void show(intx) {
final int y = 5;
//System.out.println("姓名:" + this.name + "年龄:" + this.age + "性别:" + this.gender);
classInner {
public voidhello() {
System.out.println("hello-------"+x + " ," +y);
}
}
Inner inner = newInner();
inner.hello();
}
/**
* 内部类
*/
public static voidmain(String[] args) {
//声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰
new Outer().show(8);
}
}
hello-------8 ,5
1.6、为什么内部类能直接访问外部类中的成员呢?
因为内部类持有了外部类的引用,外部类名.this。 (默认省略)
packagecom.day08.innerclass.demo4;
public classOuter {
private int num=3;
classInner{
private int num=4;
public voidshow(){
int num=5;
//局部变量System.out.println(num);
//内部类的成员变量
System.out.println(this.num);
//外部类的成员变量
System.out.println(Outer.this.num);
}
}
public static voidmain(String [] args){
new Outer().newInner().show();
}
}
二、匿名内部类
2.1、匿名内部类概念
内部类可以继承或实现一个外部类或者接口。
格式:
new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
简单理解:
就是建立一个带内容的外部类或者接口的子类匿名对象。
什么时候使用匿名内部类呢?
通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。
好处:
增强阅读性。
2.2、重写类中的方法
packagecom.day08.innerclass.demo5;
/**
* 抽象类
* @author denny
*
*/
public abstract classPerson {
private String name="张三";
public voidshow(){
System.out.println(this.name);
}
publicString getName() {
returnname;
}
public voidsetName(String name) {
this.name =name;
}
}
packagecom.day08.innerclass.demo5;
/**
* 外部类
*
* @author denny 实现有一个方法的抽象类的匿名内部类
*
*/
public classOuter {
private int num = 3;
public voidsay() {
new Person() {// 匿名内部类
public void show() { //重写抽象类中的方法,抽象方法,普通方法都可以
System.out.println("..............." +num);
}
}.show(); //对象创建完成,调用自己}
public static voidmain(String[] args) {
newOuter().say();
}
}
结果:
...............3
第二种写法,适后重写了多个方法
packagecom.day08.innerclass.demo5;
/**
* 外部类
*
* @author denny 实现有一个方法的抽象类的匿名内部类
*
*/
public classOuter {
private int num = 3;
public voidsay() {
Person person=new Person() {// 匿名内部类
public void show() { //重写抽象类中的方法,抽象方法,普通方法都可以
System.out.println("..............." +num);
}
};
//对象创建完成person.show();
}
public static voidmain(String[] args) {
newOuter().say();
}
}
2.3、示例使用接口的方式
packagecom.day08.innerclass.demo6;
/**
* 接口
* @author denny
*
*/
public interfaceBirdPro {
/**
* 2个抽象方法
*/
public voidshout();
public voidaccact();
}
packagecom.day08.innerclass.demo6;
public classOuter {
private String name="张三";
public voidshow(){
int y=3;
BirdPro birdPro=newBirdPro(){
//实现接口中的方法@Override
public voidshout() {
System.out.println(name+","+y);
}
@Override
public voidaccact() {
System.out.println(y+","+name);
}
};
birdPro.shout();
birdPro.accact();
}
publicString getName() {
returnname;
}
public voidsetName(String name) {
this.name =name;
}
public static voidmain(String[] args) {
newOuter().show();
}
}
结果:
张三,3
3,张三
2.4、把匿名内部类做参数传递
通常的使用场景之一:当函数参数是接口类型时,而且接口中的方法不超过三个。可以用匿名内部类作为实际参数进行传递。
packagecom.day08.innerclass.demo6;
/**
* 接口
*
* @author denny
*
*/
public interfaceBirdPro {
/**
* 2个抽象方法
*/
public voidshout();
public voidaccact();
}
packagecom.day08.innerclass.demo6;
classInnerDemo {
public static voidmain(String[] args) {
// 把接口做参数传递
show(newBirdPro() {
// 实现接口中的方法@Override
public voidshout() {
System.out.println("叫声");
}
@Override
public voidaccact() {
System.out.println("攻击");
}
});
}
public static void show(BirdPro birdPro) {// 做参数
// 调用birdPro.accact();
birdPro.shout();
}
}
2.5、 初始化顺序
packagecom.day08.innerclass.demo2;publicclassFu {intnum = 9;static{
System.out.println(" static Fu");
}
{
System.out.println("Fu");
}
Fu() {super();//Object//显示初始化//构造代码块初始化show();//构造函数调用方法,如果子类已经重写了,父类的方法,则执行子类的方法,但这时,成员还没有初初始化,所以为默认值}voidshow() {
System.out.println("fu show " + num);//被覆盖,运行子类的}
}
packagecom.day08.innerclass.demo2;publicclassZiextendsFu {intnum = 8;static{
System.out.println(" static Zi");
}
{
System.out.println("Zi");
}
Zi(){super();//显示初始化//构造代码块初始化show();
}voidshow(){
System.out.println("zi show " +num);
}
}
packagecom.day08.innerclass.demo2;publicclassTest1 {publicstaticvoidmain(String[] args) {newZi();
}
}
结果:
staticFustaticZi
Fu
zi show0Zi
zi show8