1、java类与类之间的关系:
1、继承:子类继承父类,子接口继承父接口。
class Son extends Father{}
interface iS extends IF {}
2、实现接口:
class Computer implements Usb{ }
2、内部类:
一个类的内部又嵌套了另一个完整的类,被嵌套的类称为内部类。
内部类是类的第五大成员:属性、方法、构造器、代码块、内部类。内部类包括:
若:定义在外部类的局部位置上(如方法体内、或代码块中):
1、局部内部类(有类名)。
2、匿名内部类(没有类名,重点!!!)。
若:定义在外部类的成员位置上:
1、静态内部类(static修饰)。
2、成员内部类(没有static修饰) 。
class Outer {
// 1、属性
private String name;
// 2、方法
public void say() {
System.out.println("hello word");
}
// 3、构造器
public Outer(String name) {
this.name = name;
}
// 4、代码块
{
System.out.println("我是外部类的代码块");
}
// 5、内部类
class Inner {
}
}
1、局部内部类:
细节:
- 1、局部内部类可以直接访问外部类所有成员,包括私有的。
* 2、局部内部类不能添加访问修饰符,但是可以使用final修饰,使用final修饰后该类不可被继承。
* 3、作用域:仅仅在定义它的方法或者代码块中。
* 4、外部类如何访问内部类成员:在外部类定义该内部类的方法内创建对象再访问。
* 5、外部类不能访问局部内部类(局部内部类地位就是一个局部变量)。
* 6、外部类和局部内部类成员重名,遵循就近访问原则;如果要访问外部类成员,可以使用:
* (外部类名.this.成员访问)(new 外部类.成员)。
package com.hsf.extends_.innerclass;
public class LocalInnerClass {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.outMethod02();
}
}
class Outer02 {
/*
* 细节:
* 1、局部内部类可以直接访问外部类所有成员,包括私有的。
* 2、局部内部类不能添加访问修饰符,但是可以使用final修饰,使用final修饰后
* 该类不可被继承。
* 3、作用域:仅仅在定义它的方法或者代码块中。
* 4、外部类如何访问内部类成员:在外部类定义该内部类的方法内创建对象再访问。
* */
private int age = 10;
private int num = 20;
public void outMethod01() {
System.out.println("outMethod01");
}
public void outMethod02() {
System.out.println("outMethod");
class inner {
private int age = 30;
public void innerMethod() {
System.out.println("innerMethod");
System.out.println(age + " " + num); // 30 20
System.out.println(Outer02.this.age); // 10
System.out.println(new Outer02().age); // 10
outMethod01();
}
}
inner inner = new inner();
inner.innerMethod();
}
}
2、匿名内部类:
1、本质还是类。
2、该类没有名字(底层有名字,但是看不到)
3、同时还是一个对象。1、可以直接访问外部类所有成员,包括私有的。
2、不能添加访问修饰符。
3、作用域:在定义的方法或者代码块中。
4、属性重名:遵循就近原则,访问外部类:外部类名.this.成员。
package com.hsf.extends_.innerclass.anonyinnerclass;
public class FirstFace {
public static void main(String[] args) {
new Outer().method();
}
}
class Outer {
/*
* 基于接口的匿名内部类:
* 1、需求:如果要实现IA接口,那么该如何做呢?
* 2、传统方法:写一个类,使用implements来实现该接口。
* 3、但是如果这个类只是使用一次,创建一个类的话效率低,浪费资源。
* 4、解决:使用匿名内部类:不用创建类即可实现接口。
* */
private int age = 10;
public void method() {
/*
tiger的编译类型:IA
tiger的运行类型:匿名内部类
匿名类名类:
class Outer$1(计算机底层分配) implements IA {
@Override
public void cry() {
System.out.println("老虎叫...");
}
}
new解读:jdk底层在创建匿名内部类 Outer$1,马上就创建了Outer$1的实例(new),并将该实例地址返回给tiger
匿名内部类使用一次,就不能再使用了。
* */
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎叫...");
}
};
System.out.println(tiger.getClass()); // Outer$1 外部类名+$+序号
tiger.cry();
/*
* 基于类与类的匿名内部类:
* father编译类型:Father
* father运行类型:Outer$2
* class Outer$2 extends Father {
* }
* */
Father father = new Father("jack") {
@Override
public void test() {
System.out.println("匿名内部类重写了test()");
}
};
System.out.println(father.getClass());
father.test();
new Father("mary") {
@Override
public void test(int num) {
System.out.println(num);
}
}.test(12);
}
}
interface IA {
void cry();
}
// 传统实现接口的写法:
//class Dog implements IA {
// @Override
// public void cry() {
// System.out.println("小狗叫...");
// }
//}
class Father {
public Father(String name) {
System.out.println("姓名:" + name);
}
public void test() {
}
}
匿名内部类实践:将匿名内部类当做实参传递,简洁高效
将匿名内部类当做方法的参数传递:
如果某个实现类只需要使用一次,就可以使用匿名内部类,如果需要多次使用,就创建一个类。
实践1:
package com.hsf.extends_.innerclass;/*
* @author HSF
* @version 8.0
*/
public class HomeWork01 {
public static void main(String[] args) {
new Cellphone().testWork(new ICalculate() {
@Override
public double work(double n1, double n2) {
return n1 + n2;
}
}, 12, 23);
new Cellphone().testWork(new ICalculate() {
@Override
public double work(double n1, double n2) {
return n1 * n2;
}
}, 15,10);
}
}
/*
* 计算器接口具有work方法,功能是运算,有一个手机类Cellphone,定义方法testWork
测试计算功能(将接口当做参数传入方法中),调用计算接口的wok方法
要求调用CellPhone对像的testWork方法,使用上名内部类
* */
interface ICalculate {
public double work(double n1, double n2);
}
class Cellphone {
public void testWork(ICalculate iCalculate, double n1, double n2) {
double result = iCalculate.work(n1, n2);
System.out.println(result);
}
}
实践2:
package com.hsf.extends_.innerclass.anonyinnerclass;
public class Achieve {
public static void main(String[] args) {
// 将匿名内部类当做实参传递,简洁高效。
/*
* class Achieve$1 implements IAA {
* @Override
public void show() {
System.out.println("这是一张水墨画~~");
}
* }
* */
f1(new IAA() {
@Override
public void show() {
System.out.println("这是一张水墨画~~");
}
});
// 传统写法:
// Picture picture = new Picture();
// f1(picture);
f1(new Picture());
}
public static void f1(IAA iaa) {
iaa.show();
}
}
interface IAA {
void show();
}
// 传统写法
class Picture implements IAA {
@Override
public void show() {
System.out.println("这是一幅水墨画~~");
}
}
实践3:
package com.hsf.extends_.innerclass.anonyinnerclass;
public class HomeWork {
public static void main(String[] args) {
new CellPhone().alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
new CellPhone().alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴们上课了");
}
});
}
}
interface Bell {
void ring();
}
class CellPhone {
public void alarmClock(Bell bell) {
bell.ring();
}
}
3、成员内部类:
1、定义在类的成员位置。
2、可以使用4种访问修饰符,因为地位和成员一样。
3、外部类访问成员内部类的两种方法:创建成员内部类对象的两种方法。
4、内部类外部类属性重名,遵循访问原则,访问外部类:外部类名.this.成员。
package com.hsf.extends_.innerclass;
public class MemberInnerClass {
public static void main(String[] args) {
// 1、第一种方法:
Outer3 outer3 = new Outer3();
// inner3是成员内部类对象。
Outer3.Inner3 inner3 = outer3.new Inner3();
// 2、第二种方法:相当于调用外部类中访问内部类的方法。
Outer3.Inner3 inner31 = outer3.getInner3();
inner31.hi();
}
}
class Outer3 {
private int age = 20;
public void say() {
System.out.println("outer");
}
class Inner3 {
private int num = 10;
public void hi() {
say(); // outer
System.out.println(age); // 20
}
}
public void use() {
new Inner3().hi();
}
// 2、第二种方法方法:写一个返回内部类的方法。
public Inner3 getInner3() {
return new Inner3();
}
}
4、静态内部类:
1、可以直接访问外部类所有静态成员,不能访问非静态成员。
2、可以使用4种访问修饰符,因为地位和成员一样。
3、外部类访问成员内部类的两种方法。
4、内部类外部类属性重名,遵循访问原则,访问外部类:外部类名.this.成员。
package com.hsf.extends_.innerclass;
public class StaticInnerClass {
public static void main(String[] args) {
new Outer4().Use();
}
}
class Outer4 {
public int age = 20;
public static String name = "李四";
static class Inner4 {
public void f1() {
// System.out.println(age);// 报错,静态内部类只能访问静态属性
System.out.println(name);
}
}
public void Use() {
new Inner4().f1();
}
}