内部类
1.什么时候使用内部类:
当一个事物的内部,还有一个部分需要完整的结构去描述,而这个内部的完整结构又只为外部事物提供服务,那么整个内部的完成结构最好使用内部类
比如:人类都有心脏,人类本身需要用属性,行为去描述,那么人类内部的心脏也需要心脏特殊的属性和行为去描述,此时心脏就可以定义成内部类,人类中的一个心脏类
2.在java中允许一个类的定义位于另外一个类内部,前者就称之为内部类,后者称之为外部类
class A{
class B{
}
}
类A就是类B的外部类
类B就是类A的内部类
3.分类:
成员内部类(静态,非静态)
局部内部类
匿名内部类(重点)
1 静态成员内部类
1.格式:直接在定义内部类的时候加上static关键字
public class A{
static class B{
}
}
2.注意:
a.内部类可以定义属性,方法,构造等
b.静态内部类可以被final或者abstract修饰
被final修饰之后,不能被继承
被abstract修饰之后,不能new
c.静态内部类不能调用外部的非静态成员
d.内部类还可以被四种权限修饰符修饰
3.调用静态内部类成员:
外部类.内部类 对象名 = new 外部类.内部类()
public class Person {
public void eat(){
System.out.println("人要干饭");
}
static class Heart{
public void jump(){
System.out.println("心脏哐哐哐跳");
}
}
}
public class Test01 {
public static void main(String[] args) {
// 外部类.内部类 对象名 = new 外部类.内部类()
Person.Heart heart = new Person.Heart();
heart.jump();
}
}
2 非静态成员内部类
1.格式:直接在定义内部类的时候加上static关键字
public class A{
class B{
}
}
2.注意:
a.内部类可以定义属性,方法,构造等
b.静态内部类可以被final或者abstract修饰
被final修饰之后,不能被继承
被abstract修饰之后,不能new
c.静态内部类不能调用外部的非静态成员
d.内部类还可以被四种权限修饰符修饰
3.调用非静态内部类成员:
外部类.内部类 对象名 = new 外部类().new 内部类()
public class Person {
public void eat(){
System.out.println("人要干饭");
}
class Heart{
public void jump(){
System.out.println("心脏哐哐哐跳");
}
}
}
public class Test01 {
public static void main(String[] args) {
// 外部类.内部类 对象名 = new 外部类().new 内部类()
Person.Heart heart = new Person(). new Heart();
heart.jump();
}
}
外部类的成员变量和内部类的成员变量以及内部类的局部变量重名时,怎么区分?
public class Student { String name = "金莲"; class Heart{ String name = "大郎"; public void display(String name){ System.out.println(name);//内部类的局部变量 System.out.println(this.name);//内部类的成员变量 System.out.println(Student.this.name);//外部类的成员变量 } } } public class Test02 { public static void main(String[] args) { Student.Heart heart = new Student().new Heart(); heart.display("涛哥"); } }
3.局部内部类
3.1.局部内部类基本操作
1.可以定义在方法中,代码块中,构造中
public class Person {
public void eat(){
class Heart{
public void jump(){
System.out.println("心脏哐哐哐的跳");
}
}
new Heart().jump();
}
}
public class Test01 {
public static void main(String[] args) {
Person person = new Person();
person.eat();
}
}
3.2.局部内部类实际操作
3.2.1.接口类型作为方法参数传递和返回
1.接口作为方法参数,传递实参时,传递的是实现类对象
2.接口作为返回值类型返回,实际返回的是实现类对象
public interface USB {
public abstract void open();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标打开");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
method(mouse);
System.out.println("================");
USB usb = method01();//USB usb = new Mouse();
usb.open();
}
/*
接口作为方法参数,传递实参时,传递的是实现类对象
*/
public static void method(USB usb){//USB usb = mouse -> 多态
usb.open();
}
/*
接口作为返回值类型返回,实际返回的是实现类对象
*/
public static USB method01(){
//Mouse mouse = new Mouse();
//return mouse;
return new Mouse();
}
}
3.2.2.抽象类作为方法参数和返回值
1.抽象类作为方法参数传递,传递实参时,传递的是其子类对象
2.抽象类作为方法返回值类型返回时,实际返回的是其子类对象
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗啃骨头");
}
}
public class Test02 {
public static void main(String[] args) {
Dog dog = new Dog();
method01(dog);
System.out.println("=================");
Animal animal = method02();//Animal animal = new Dog()
animal.eat();
}
public static void method01(Animal animal){//Animal animal = dog
animal.eat();
}
public static Animal method02(){
return new Dog();
}
}
3.2.3.普通类做方法参数和返回值
普通类作为方法参数传递,传递的是对象
普通类作为方法返回值返回,返回的是对象
public class Person {
public void eat(){
System.out.println("人要干饭");
}
}
public class Test03 {
public static void main(String[] args) {
Person person = new Person();
method01(person);
System.out.println("==================");
Person person1 = method02();//Person person1 = new Person()
person1.eat();
}
public static void method01(Person person){
person.eat();
}
public static Person method02(){
return new Person();
}
}
3.2.4.局部内部类实际操作
public interface USB {
void open();
}
public class Test01 {
public static void main(String[] args) {
USB usb = method();//USB usb = new Mouse()
usb.open();
}
public static USB method(){
//局部内部类
class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标打开");
}
}
return new Mouse();
}
}
4.匿名内部类(重点)
所谓的匿名内部类,可以理解为没有显式声明出类名的内部类
1.问题描述:我们如果想实现接口,简单使用一次抽象方法,我们就需要创建一个实现类,实现这个接口,重写抽象方法,还要new实现类对象,所以我们在想如果就单纯的想使用一次接口中的方法,我们能不能不这么麻烦呢?可以
a.创建实现类,实现接口
b.重写方法
c.创建实现类对象
d.调用方法
2.如果就想单纯的使用一下接口中的方法,我们就没必要经过以上四步了,我们可以四合一
3.匿名内部类怎么学:就按照一种格式来学,这一种格式就代表了实现类对象或者子类对象
4.格式:
new 接口/抽象类(){
重写方法
}.重写的方法();
=================================
类名 对象名 = new 接口/抽象类(){
重写方法
}
对象名.重写的方法();
public interface USB {
void open();
void close();
}
public class Test01 {
public static void main(String[] args) {
new USB(){
@Override
public void open() {
System.out.println("usb打开了");
}
@Override
public void close() {
System.out.println("usb关闭了");
}
}.open();
System.out.println("===================");
USB usb = new USB() {
@Override
public void open() {
System.out.println("USB打开了");
}
@Override
public void close() {
System.out.println("USB关闭了");
}
};
usb.open();
usb.close();
}
}
1.什么时候使用匿名内部类:
当简单调用一次接口中的方法,我们就可以使用匿名内部类
2.将一种格式代表实现类对象或者子类对象来看待,来学习
3.匿名内部类会编译生成的,咱们不要管,我们只需要利用咱们讲的格式去new对象,调用重写的方法即可
4.1 匿名内部类复杂用法_当参数传递
public interface USB {
void open();
}
public class Test01 {
public static void main(String[] args) {
method01(new USB() {
@Override
public void open() {
System.out.println("usb打开了");
}
});
}
public static void method01(USB usb){
usb.open();
}
}
4.2 匿名内部类复杂用法_当返回值返回
public interface USB {
void open();
}
public class Test02 {
public static void main(String[] args) {
USB usb = method01();
usb.open();
}
public static USB method01(){
return new USB() {
@Override
public void open() {
System.out.println("USB打开了");
}
};
}
}