02java

1.继承

(1).父类非私有的成员,子类可以直接访问;父类私有的成员,子类想要访问,父类需要提供公共方法。

父类base:

package com.qhx.extend_;
//父类
public class Base {
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;

    public Base() {
        System.out.println("base0....");
    }

    public void test100() {
        System.out.println("test100");
    }
    protected void test200() {
        System.out.println("test200");
    }
    void test300() {
        System.out.println("test300");
    }
    private void test400() {
        System.out.println("test400");
    }
    //n4是私有的,可以提供公共方法,让子类得到n4
    public void  getn4(){
        System.out.println(n4);
    }
}

子类sub:

package com.qhx.extend_;
public class Sub extends Base{
        public Sub(){
            System.out.println("sub()...");
        }
        public void sayok(){
            System.out.println(n1+n2+n3);//n4是私有属性
            test100();
            test200();
            test300();
            //test400();父类的私有方法,子类不能访问
            getn4();//通过公共方法得到n4
        }
}

测试:

package com.qhx.extend_;
public class ExtendsDetail {
    public static void main(String[] args) {
        Sub sub=new Sub();
        sub.sayok();
    }
}

(2).子类必须调用父类的构造器,完成父类初始化。

(3).创建子类对象时,会默认先调用父类的无参构造器;如果父类没有无参构造器,需要在子类构造器中使用super()来规定要调用父类那个构造器。

package com.qhx.extend_;

public class ExtendsDetail2 {
    public static void main(String[] args) {
        z z1=new z();
        System.out.println("对象2:");
        z z2=new z("qwq");
    }
}
class f{
    private String name;
    public f(){
        System.out.println("父类无参构造器");
    }
    public f(String name){
        this.name=name;
        System.out.println("父类name构造器");
    }
    //set,get就不写了,主要看构造器
}
class z extends f{

    public z(){
        //super();默认调用父类无参构造器
        super("aaa");//指定调用父类有参构造器
        //参数随便写一个,如果对象自己有用name
        System.out.println("子类无参构造器");
    }
    public z(String name){
        super(name);
        System.out.println("子类name构造器");
    }
}

2.super关键字

(1).访问父类属性

super.属性名

(2).访问父类方法

super.方法名(参数列表);

(3).访问父类构造方法

super(参数列表)

只能写一次,只能放在第一行

(4).super可以访问父类的父类,采用就近原则

3.重写

(1).方法重写

1).子类的方法名字,参数个数要与父类一致

2).子类方法的返回类型要和父类方法返回值一致,或是子类

3).子类方法不能缩小父类方法的权限

(2).属性没有重写之说

访问属性看编译类型,访问方法看运行类型

先编译,后运行,如果访问方法,先看子类再看父类

public class a {
    public static void main(String[] args) {
        AA a=new BB();
        System.out.println(a.n);//输出多少,输出1
        //访问属性看编译类型
    }
}
class AA{//父类
    public int n=1;
}
class BB extends AA{//父类
    public int n=10;
}

4.多态

(1).方法多态

方法重写

方法重载

都体现多态

(2).对象多态

编译类型=运行类型;

例:主人给动物喂食物

master类

package com.qhx.poly_;

public class Master {
    public String name;
    public Master(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //多态
    public void feed(Animal animal,Food food){
        System.out.println("主人"+name+"给"+animal.getName()+"喂"+food.getName());
    }
}

animal类

package com.qhx.poly_;

public class Animal {
    private   String name;

    public Animal(String name) {
        this.name = name;
    }
    public void cry(){
        System.out.println("动物叫");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
    public  void  cry(){
        System.out.println("小猫喵喵叫");
    }
}
class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
    public  void  cry(){
        System.out.println("小狗旺旺叫");
    }
}

 food类

package com.qhx.poly_;

public class Food {
    public String name;

    public Food(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Fish extends Food{
    public Fish(String name) {
        super(name);
    }

}
class Bone extends Food{
    public Bone(String name){
        super(name);
    }

}

 测试类

package com.qhx.poly_;

public class poly01 {
    public static void main(String[] args) {
        Master master=new Master("tom");
//        对象多态
        Animal animal=new Cat("小花猫");
//        编译类型=运行类型
        animal.cry();//运行时调用的是Cat中的cry方法
//        运行时animal的运行类型是cat
        Food food=new Fish("小黄鱼");
        master.feed(animal,food);

        Dog dog = new Dog("大黄");
        Bone bone=new Bone("骨头");
//        master.feed(animal,bone);
    }
}

(3).向上转型

先编译,再运行。

编译通过,运行时方法先看子类,再看父类

package com.qhx.poly_.detail;

public class polyDetail {
    public static void main(String[] args) {
        //向上转型
        //可以访问父类的成员,遵守访问权限
        //不能访问子类的私有方法
        Object obj=new cat();//可以,object也是cat的父类
        animal animal1 = new cat();
        //animal1.catmouse();错误
        //编译就不通过,编译时看animal,而catmouse是cat特有的方法
        animal1.eat();//通过
        //编译通过,然后看运行类型是cat类,先调用cat中的eat方法
        //如果cat里面没有eat方法,再看父类
    }
}

(4).向下转型

注意向下转型要和向上转型的运行类型一致

package com.qhx.xx;

public class detail {
    public static void main(String[] args) {
        Animal animal = new Cat();
        //向上转型,可以访问子类父类都有的方法,不能访问子类的特有方法
        System.out.println(animal.age);//10
        Cat cat=(Cat)animal;
        //向下转型,可以访问子类特有方法
        System.out.println(cat.age);//20
        //属性没有重写之说,直接看编译类型

    }
}
class Animal{
    public int age=10;
    public void eat(){}
}
class Cat extends Animal{
    public int age=20;
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void zhua(){
        System.out.println("猫抓老鼠");
    }
}

(5).动态绑定机制

动态绑定看运行类型

当调用对象的方法时,该方法会和该对象的内存地址绑定,

当调用对象属性时,没有动态绑定机制

public class c {
    public static void main(String[] args) {
        E e=new F();
        //System.out.println(e.sum());//30
        System.out.println(e.sum1());//40
        //如果子类没有sum()函数
        System.out.println(e.sum());//30
        //去调用父类sum()
        //但是getn()子类里有,会和e绑定,所以调用子类getn(),n=20
        //再加10>30
    }
}
class E{
    public int n=10;
    public int sum(){
        return getn()+10;
    }
    public int sum1(){
        return n+10;
    }
    public int getn(){
        return n;
    }
}
class F extends E{
    public int n=20;
//    public int sum(){
//        return getn()+20;
//    }
    public int sum1(){
        return n+10;
    }
    public int getn(){
        return n;
    }
}

(6). 多态数组

应用实例:现有一个继承结构如下:要求创建1个Person对象、2个Student 对象和2个
Teacher对象,统一放在数组中,并调用每个对象say方法.如何调用子类特有的方法,比如
Teacher有一个 teach, Student有一个, study。怎么调用?

向下转型才能访问子类的特有方法

public class b {
    public static void main(String[] args) {
        Person p[]=new Person[5];
        p[0]=new Person("a",12);
        p[1]=new Student("b",13);
        p[2]=new Student("c",13);
        p[3]=new Teacher("d",40);
        p[4]=new Teacher("e",40);
        for (int i = 0; i < p.length; i++) {
            p[i].say();
            if(p[i] instanceof Student){
                ((Student)p[i]).study();
            }else if(p[i] instanceof  Teacher){
                ((Teacher)p[i]).teach();
            }else {
                System.out.println("没有");
            }
        }

    }
}
class Person{
    private String name;
    private  int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void say(){
        System.out.println("person的say方法");
    }

    public String getName() {
        return name;
    }
}
class Student extends Person{
    public Student(String name, int age) {
        super(name, age);
    }

    public void study(){
        System.out.println("学生"+getName()+"正在学习");
    }
    public void say(){
        System.out.println("student的say方法");
    }
}
class  Teacher extends Person{
    public Teacher(String name, int age) {
        super(name, age);
    }
    public void teach(){
        System.out.println("老师"+getName()+"正在教学");
    }
    public void say(){
        System.out.println("teacher的say方法");
    }
}

(7).多态参数

上面给动物喂食

5.instanceof方法和==和equals方法和hashCode()和toString方法

(1).instanceof

xx instanceof XX,判断xx的运行类型是不是XX类型,或子类型

System.out.println(cat instanceof Cat);//true
System.out.println(cat instanceof Object);//true

(2).==

可以判断基本类型和引用类型

判断基本类型看值是否相等

判断引用类型看地址是否相同

package com.qhx.equals_;

public class a {
    public static void main(String[] args) {
        int n=10;
        double n2=10.0;
        System.out.println(n==n2);//true

        B b = new B();
        B a=b;
        B c=b;
        System.out.println(a==c);//true
    }
}
class B{}

(3).equals

equals是obj里的方法,只能判断引用类型,地址是否相同
但是子类中往往重写该方法,用来判断内容相等
public class b {
    public static void main(String[] args) {
        //equals是obj里的方法,只能判断引用类型,地址是否相同
        //但是子类中往往重写该方法,用来判断内容相等

        A a = new A();
        A b=new A();
        System.out.println(a.equals(b));//false
        //obj里的equals方法,判断地址

        System.out.println("aa".equals("bb"));//false
        //string里的equals方法判断内容


    }
}
class  A{

}

(4).hashCode()

返回对象的hashCode编码

编码是通过地址号来的

public class hashCode_ {
    public static void main(String[] args) {
        A a1=new A();
        A a2=a1;
        System.out.println(a1.hashCode()==a2.hashCode());
        //true
    }
}
class A{

}

(5).toString() 

默认返回:全类名+@+哈希值的十六进制

子类往往重写此方法

输出一个对象时默认调用该方法

public class b {
    public static void main(String[] args) {
        A a1=new A();
        System.out.println(a1);
        //A类不重写toString,输出com.qhx.toString_.A@1e643faf
        //A类重写,输出 "我重写tostring方法"
    }
}
class A{
    public String  toString(){
        return "我重写tostring方法";
    }

6.static关键字

(1).类变量/静态变量

static声明,可以被所有对象实例访问共享,也可以被类名访问

当所有对象都要共享一个变量时,使用

遵守访问权限

package com.qhx.static_;

public class ChildGane {
    public static void main(String[] args) {

        Child a1 = new Child("a");
        a1.join();
        a1.count++;
        Child a2 = new Child("b");
        a2.join();
        a2.count++;
        Child a3 = new Child("c");
        a3.join();
        a3.count++;
        System.out.println(Child.count);
        System.out.println(a1.count);//3
        System.out.println(a2.count);//3
        System.out.println(a3.count);//3

    }
}
class Child{
    private String name;
    //静态变量,类变量,会被child对象所有的实例共享
    //类变量可以通过类名直接访问
    public static int count=0;
    public void join(){
        System.out.println("加入游戏");
    }

    public Child(String name) {
        this.name = name;
    }
}

(2).静态方法/类方法

类名和对象实例都可以访问静态方法

静态方法可以访问静态属性,非静态方法也可以访问静态属性

非静态成员可以访问静态和非静态

静态方法中没有this

静态方法只能访问静态成员,不能访问普通成员

package com.qhx.static_;

public class StudentFee {
    public static void main(String[] args) {
        Stu stu1 = new Stu();
        //类名可以访问静态方法和静态变量
        //实例对象也可以访问静态方法和静态变量
        //stu1.getFee(100);对
        Stu.getFee(100);
        Stu stu2 = new Stu();
        Stu.getFee(200);
        Stu.showFee();
    }
}
class Stu{
    public static int fee=0;
    //静态方法可以访问静态属性
    //静态方法也可以
    public static void getFee(int f){
        System.out.println(Stu.fee+=f);
    }
    public  static void  showFee(){
        System.out.println(Stu.fee);
    }
}

7.main方法

public class a {
    public static void main(String[] args) {
        //public 不在一个类中,设为public
        //main方法调用不需要创建对象,所以是static
        //
        //main方法中的参数如何传递进去
        //在程序执行的时候 java a tom jabk smail
        //传递3个参数
    }
}

查看参数,看这个文章

8.代码块

代码块分为两种,static修饰的静态代码块,和不被修饰的非静态代码块

普通代码块

(1).普通代码块会在创建对象时被调用,每创建一次,调用一次

(2).代码块写在类里面

(3).访问类的静态成员,普通代码块不会被调用,静态代码块会被调用

public class a {
    public static void main(String[] args) {
        Mover m1=new Mover("喜羊羊");
        Mover m2=new Mover("喜羊羊",12);
    }
}
class Mover{
    public String name;//名字
    public int price;//价格
    {
        System.out.println("电视开始了");
        System.out.println("电视广告");
        System.out.println("电视结束");
    }
    public Mover(String name) {
//        System.out.println("电视开始了");
//        System.out.println("电视广告");
//        System.out.println("电视结束");
        //上面代码块非静态每次都会被调用
        this.name = name;
    }

    public Mover(String name, int price) {
//        System.out.println("电视开始了");
//        System.out.println("电视广告");
//        System.out.println("电视结束");
        //上面代码块非静态每次都会被调用
        this.name = name;
        this.price = price;
    }
}

静态代码块:

什么时候静态代码块会被调用:类加载的时候,下面都是

(1).创建对象实例会被调用

(2).创建子类对象,父类代码块也会被调用,父类先被加载

(3).访问静态成员时

(4).静态代码块之后被调用一次,之后就失效了

重要:

在一个类中的执行流程

(1).先执行静态代码块,和静态属性,谁在前面谁先来

(2).再执行普通代码块和普通属性,谁在前面谁先来

(3),最后调用构造器

在多个继承类的执行流程

(1).父类静态代码块,和静态属性初始化

(2).子类静态代码块,和静态属性初始化

(3).父类普通代码块和普通属性初始化

(4).父类构造器

(5).子类普通代码块和普通属性初始化

(6).子类构造器

在子类构造器中隐藏super()和子类的普通代码块

先完成类的加载,也就是静态初始化

9.单例设计模式

某个类中只有一个实例对象

饿汉单例设计模式

步骤:

     //1.构造器私有化
    //2.在类的内部创建一个静态对象
    //3.对外暴露一个静态方法
    //4.通过静态方法返回这个对象
    //只有修饰为public static其他类才可以直接调用,私有的静态对象,就获取到了

public class a {
    public static void main(String[] args) {
        GirlFriend gril=GirlFriend.getInstance();

    }
}
class GirlFriend{
    //1.构造器私有化
    //2.在类的内部创建一个静态对象
    //3.对外暴露一个静态方法
    //4.通过静态方法返回这个对象
    //只有修饰为public static其他类才可以直接调用,私有的静态对象,就获取到了
    private String name;
    private static GirlFriend gf=new GirlFriend("qwq");//
    private GirlFriend(String name) {
        this.name = name;
    }
    public static GirlFriend getInstance(){
        return gf;
    }
}

懒汉单例设计模式

//1.构造器私有化

//2.创建一个静态私有空对象

//3.创建一个静态公用方法,判断对象是否为null,如果是创建对象,不是返回对象

public class b {
    public static void main(String[] args) {
        G g1=G.returnG();
        System.out.println(g1.toString());
        G g2=G.returnG();
        //对象之后创建一次g1=g2
    }
}
class G{
    private String name;
    private  static G g;
    //类加载的时候构造器不会被调用,静态代码块会被调用

    private G(String name) {
        this.name = name;
    }
    public static G returnG(){
        if (g==null){
            g=new G("aaa");
        }
        return g;
    }

    public String toString() {
        return name;
    }
}

10.final关键字

(1).可以修饰属性,方法,局部变量

什么时候使用final关键字

(1).不希望类被继承时

(2).不希望方法被重写时

(3).不希望某个属性被修改时

(4).不希望某个局部变量被修改时

(5).不能修饰构造器

细节:

(1).final修饰的属性必须初始化,可以在定义时,构造器,代码块中初始化

(2).静态属性初始化要在定义时,静态代码块中。

package com.qhx.final_;

public class a {
    public static void main(String[] args) {
        Y y=new Y(1);
        y.gets();
    }
}
class Y{
    private int r;
    //1.在定义时被初始化
    //public final static double  PI=3.14;
    public final static double  PI;
    public Y(int r) {
       
        this.r = r;
    }
    //2.在静态代码块中
    static {
        PI=3.14;
    }
    public void gets(){
        System.out.println(2*PI*r);
    }
}

11.抽象类

什么是抽象类

1.一个类存在抽象方法,这个类就是抽象类;抽象类不一定有抽象方法

2.抽象方法和空方法不一样 ,抽象方法没有方法体,也就是没有花括号 ,空方法有方法体

3.抽象类和抽象方法使用abstract修饰

4.抽象类不能被实例化

5.如果一个类继承了抽象类,那他必须重写抽象类中所以的抽象方法,除非他自己也声明为抽象类

6.抽象方法不能使用private,static,final来修饰,与重写违背 ,static修饰方法,可是抽象方法没有方法体

package com.qhx.abstract_;

public class Abstract01 {
    public static void main(String[] args) {
//            new Aniaml();错误,1.抽象类不能被实例化

    }
}
abstract class Aniaml{
    private String name;
    //2.abstract不能修饰属性,只能修饰方法和类

    public Aniaml(String name) {
        this.name = name;
    }
    //父类方法不确定
    //抽象方法和空方法不一样
    //3.抽象方法没有方法体,也就是没有花括号
    //空方法有方法体
    //抽象方法
    public abstract  void eat();
    //普通方法
    public void hi(){};
}
abstract class  A{
    //4.抽象类,可以没有抽象方法
}
abstract class B{
    //5.有抽象方法一定是抽象类
    public abstract void  hello();
}
//6.抽象类和普通类一样,可以有构造器

应用:模板设计模式

把一样的提取出来,不一样的写成抽象方法。



public class test1 {
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.calculateTime();
    }
}
abstract class Template{
    public abstract void job();
    public void calculateTime(){
        long start=System.currentTimeMillis();
        job();//动态绑定
        long end=System.currentTimeMillis();
        System.out.println("执行时间"+(end-start));
    }

}
class Sub extends Template{
    @Override
    public void job() {
        long num=0;
        for (int i = 1; i <= 800000; i++) {
            num+=i;
        }
    }
}

12.接口

1.定义接口interface

(1).jdk7之前接口里的方法都是抽象方法,jdk8以后可以有静态方法和默认实现方法

  (2).抽象方法可以省略abstract

  (3).默认实现方法要用default修饰

public interface Usb {//接口
    public static final int n1=100;//等价int n1=100
    //默认方法
    default public void lian(){
        System.out.println("连接成功");
    }
    //静态方法
    static public void n1(){
        System.out.println("10");
    }
    //抽象方法
    public void start();
    public void end();

}

细节:

(1).接口中的方法都是public方法

(2).一个类可以实现多个接口

(3).接口中的属性只能是public static final的,int n1=1;等价于public static final int n1=1;

(4).访问接口属性:接口名.属性名

(5).接口不能继承其他类,但是能继承其他接口

class a implements b,c{
    
}
interface a extends b,c{
    
}

2.实现接口implement

接口里的抽象方法都要实现,快捷键alt+enter(没设置呢)

除非实现接口的类是抽象类,可以不用实现接口方法

public class Phone implements Usb{
    public void start(){
        System.out.println("手机开始工作");
    }
    @Override
    public void end() {
        System.out.println("手机停止工作");
    }
}

3.接口使用场景

3个人分别编写三个类完成对mysql,oracle,db2的连接

每个人写的方法名字可能都不一样

使用接口可以规定名字必须是什么

实现:

public class interface02 {
    public static void main(String[] args) {
        Mysql mysql = new Mysql();
        t(mysql);
        OracleDB oracleDB = new OracleDB();
        t(oracleDB);

    }
    public static void t(DBinterface db){
        db.connect();
        db.close();
    }
}

接口:

public interface DBinterface {
    public void connect();
    public void close();
}

mysql连接类:

public class Mysql implements DBinterface{
    public void connect(){
        System.out.println("连接mysql");
    }
    @Override
    public void close() {
        System.out.println("关闭mysql");
    }
}

4.练习

5.继承类和实现接口区别

实现接口:实现一些接口中的方法;那个类需要接口中的方法,哪个类实现接口;补充父类没有的方法

继承:实现父类的一些方法

class a extends b implements c,d{
    
}

6.接口多态

(1).多态参数

1).上面Compater类的work方法的形参是Usb类型的,既可以接受手机类对象,又可以接收其他类对象;只有是实现了接口的类都可以接收

public class interface01 {
    public static void main(String[] args) {
        //
        Phone phone = new Phone();
        Compater compater = new Compater();
        Camera camera = new Camera();
        compater.work(phone);
        compater.work(camera);
    }
}

2).接口类型的变量可以指向实现接口的实例

public class interface03 {
    public static void main(String[] args) {
        IF if1=new Mon();
        IF if2=new Car();
    }
}
interface IF{
}
class Car implements IF{}
class Mon implements IF{}

(2).多态数组

Usb类型的数组,存放Phone和相机对象,Phone类还有一个对象方法call(),请变量Usb数组,如果是Phone对象,要调用Usb接口的方法,还要调用call()方法。

public class interface04 {
    public static void main(String[] args) {
        Usb u1[]=new Usb[2];
        u1[0]=new Phone();
        u1[1]=new Xji();
        for (int i = 0; i < u1.length; i++) {
            u1[i].com();//动态绑定
            if (u1[i] instanceof Phone){
                ((Phone) u1[i]).call();
            }
        }
    }
}
interface Usb{
    public void com();
}
class Phone implements Usb{
    public void com(){
        System.out.println("打开手机");
    }
    public void call(){
        System.out.println("打电话");
    }
}
class Xji implements Usb{
    @Override
    public void com() {
        System.out.println("打开相机");
    }
}

(3).多态传递

public class interface05 {
    public static void main(String[] args) {
        IA ia=new Teacher();
        IB ib=new Teacher();
    }
}
interface IA{}
interface IB extends IA{}//IB继承IA
class Teacher implements IB{//Teacher继承IB,IB继承IA,这样IA也可以创建Teacher类型的对象

}

7.练习

interface A{
    int n=1;
}
class B{
    int n=2;
}
public class C extends B implements A{
    public void pN(){
        //访问接口的:接口名.n
        //访问父类的:父类名.n
        System.out.println("接口的n"+A.n);
        System.out.println("父类的n"+super.n);
    }

    public static void main(String[] args) {
        new C().pN();
    }
}

13.内部类

有四种内部类:局部内部类,匿名内部类,成员内部类,静态内部类

1.什么是内部类

被其他类包裹的类叫内部类

包裹他的类叫外部类

剩下的叫外部其他类

2.局部内部类

记住:他是定义在方法和代码块中,本质还是一个类

public class LocalInnerClass {//7.外部其他类,不能访问内部类
    public static void main(String[] args) {
        Outer02 outer02 = new Outer02();
        outer02.m1();
    }
}
class Outer02{//外部类
    private  int n1=1;
    public void m2() {//私有方法
        System.out.println("m2方法。。。");
    }
    public void m1 () {//方法
        class Inner02 {//局部内部类
            //1.可以访问外部类的所以成员和方法,包括私有的
            //2.不能添加访问修饰符,因为是局部变量,但是可以用final修饰
            //3.作用域:局部内部类只在方法和代码块中
            private int n1=10;
            public void f1() {
                //4.局部内部类直接访问外部类的成员
                //8.如果外部类和局部内部类的成员重名时,默认就近原则,如果想访问外部类成员,使用外部类.this.成员
                System.out.println(n1);//10
                System.out.println(Outer02.this.n1);//1
                //n1不是静态的,要用this访问
                //Outer02.this本质就是外部类对象,即哪个对象调用的m1方法
                m2();
                }
        }
        //6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
        Inner02 inner02=new Inner02();
        inner02.f1();
    }
    {//代码块
        class Inner03{//局部内部类

        }
    }
}

3.匿名​​​​​​​内部类(重要)

本质还是一个类,他没有名字,他是一个对象,他是一个内部类

1.基本使用

基于接口的匿名内部类

public class Anonymous {
    public static void main(String[] args) {
        Outer04 outer04=new Outer04();
        outer04.method();
    }
}
class Outer04{//外部其他类
    private int n1=1;
    public void method(){
        //1.需求:想使用接口A,并创建对象
        //2.传统方式:写一个类并创建对象,这个类实现接口和接口方法,对象调用方法
        //IA tiger=new Tiger();
        //tiger.cry();
        //3.需求:tiger/dog类只使用一次,后面不再使用
        //4.解决:可以使用匿名内部类简化
        //5.triger的编译类型是IA,运行类型是匿名内部类
        /*
        * 底层 IA tiger=new class XXX implements IA{}
        * */
        //6.匿名内部类使用一次就没了,triger可以一直使用
        IA tiger=new IA(){
            public void cry() {
               System.out.println("老虎嗷嗷叫");
            }
        };
        tiger.cry();
    }
}
interface IA{//接口
    public void cry();
}
//class Tiger implements IA{
//    @Override
//    public void cry() {
//        System.out.println("老虎嗷嗷叫");
//    }
//}
//class Dog implements IA{
//    @Override
//    public void cry() {
//        System.out.println("小狗哇哇叫");
//    }
//}

基于类的匿名内部类:

public class Anonymous02 {
    public static void main(String[] args) {
        Outer05 outer05=new Outer05();
        outer05.method();
    }
}
class Outer05{//外部其他类
    private int n1=1;
    public void method(){
        //1.底层:new class Outer05$01 extend Father
        //2.编译类型Father,运行类型Outer05$01
        //3.底层会直接创建匿名内部类,并返回Outer05$02对象
        //4.参数列表会传递给构造器
        Father father=new Father("qwq"){//匿名内部类
            
            @Override
            public void test() {
                System.out.println("重写了text方法");
            }
        };//有分号,本质还是创建语句
        father.test();

        //基于抽象类的匿名内部类
        Animal animal=new Animal(){
            @Override
            public void eat() {
                System.out.println("吃饭饭");
            }
        };
        animal.eat();
    }
}
class Father{//外部其他类
    public Father(String name) {
        System.out.println(name);
    }
    public void test(){
    }
}
abstract class Animal{
    public void eat(){};
}

2.细节

public class AnonymousInnerDetail {
    public static void main(String[] args) {
        Outer06 outer06 = new Outer06();
        outer06.say();
    }
}
class Outer06{
    private int n1=1;
    public void say(){
        Student student01=new Student(){
            @Override
            public void hi() {
                System.out.println("hello");
                System.out.println(n1);
                //只能在方法里面访问外部成员
            }
            public int n1=10;

        };
        //1.两种访问方式
        //2.可以在匿名内部类的方法里直接访问外部类的所有成员,包括私有
        //3.外部其他类不能访问匿名内部类
        //4.匿名内部类访问
        student01.hi();//动态绑定

        //也可以直接调用
        new Student(){
            @Override
            public void hi() {
                System.out.println("hello");
            }
            @Override
            public void ok(String s) {
                System.out.println(s);
            }
        }.ok("qwq");
        //匿名内部类既是一个对象又是一个类
        //上面把他看做一个对象,下面看做一个类
    }
}
class Student{

    public void hi(){
        System.out.println("hi");
    }
    public void ok(String s){
        System.out.println(s);
    }
}
//抽象类、接口都可以写匿名内部类

3.应用

(1). 把匿名内部类当作实参直接传递

  例1:

public class innerClass01 {
    public static void main(String[] args) {
        f1(new AA(){
            @Override
            public void show() {
                System.out.println("aaaaa");
            }
        });//把匿名内部类看做一个参数

        //传统方法
        f1(new Pic());
    }
    public static void f1(AA a){//形参是接口类型
        a.show();
    }
}
interface AA{
    void show();
}

//传统方法,还要写一个类;但是使用匿名内部类不用写一个类了
class Pic implements AA{
    @Override
    public void show() {
        System.out.println("bbbbbbb");
    }
}

例2;

public class innerClass02 {
    public static void main(String[] args) {

       Cellphone cellphone= new Cellphone();
       cellphone.alarmClock(new Bell() {
           //编译类型是Bell,运行类型是xxx$01
           //重写了ring方法 Bell bell=new xxx01 extend Bell{ring()}
           @Override
           public void ring() {
               System.out.println("快起床");
           }
       });
       cellphone.alarmClock(new Bell() {
           @Override
           public void ring() {
               System.out.println("上课了");
           }
       });
    }
}
interface Bell{
    public void ring();
}
class  Cellphone{
    public void alarmClock(Bell bell){//形参是接口类型
        bell.ring();
    }
}

 4.成员内部类

1.定义在外部类的成员位置上

2.可以添加任意访问修饰符,因为他是一个成员

3.可以访问外部类的所以成员,包括私有

4.外部类可以创建内部类对象,再调用方法

5.成员内部类访问外部类,直接访问

6.外部其他类访问成员内部类

7.如果成员内部类成员和外部类成员重名,遵守就近原则,访问外部类通过:外部类.this.外部类成员;

public class innerclass03 {
    public static void main(String[] args) {
        Outer07 outer07 = new Outer07();
        outer07.t1();
        //3.外部其他类访问成员内部类,2种方式
        //方式一:
        //new Inner04();
        //Outer07.new Inner04();
        //这就是一个语法
        Outer07.Inner04 inner04=outer07.new Inner04();

        //方式二:写一个方法getInner04(),返回一个inner04对象
        outer07.getInner04();
    }
}
class Outer07{
    private int n1=1;
    public String name="qwq";

    public class Inner04{//成员内部类
        //1.可以直接访问外部类的所以成员,包括私有
        public void say(){
            System.out.println("n1="+n1+"name="+name);
        }
    }
    public Inner04 getInner04(){
        return  new Inner04();
    }
    //2.可以在外部类中使用成员内部类
    public void t1(){
        Inner04 inner04=new Inner04();
        inner04.say();
    }
}

5. 静态内部类

public class StaticInnerClass {
    public static void main(String[] args) {
        Outre10 outre10 = new Outre10();
        //5.外部其他类访问静态内部类:
        //方式一:new Inner10().var
        Outre10.Inner10 inner10 = new Outre10.Inner10();
        inner10.say();
        //方式二:编写一个方法返回静态内部类实例
        outre10.get();
        //方式三:编写静态方法,通过外部类名访问
        Outre10.Inner10 inner101 = Outre10.get();
    }
}
class Outre10{
    private  int n1=10;
    private static String name="张三";
    //1.放在外部类成员位置,并用static修饰
    //2.只能访问外部类的静态成员,包括私有的,非静态的不能访问
    //3.作用域为整个外部类
    //4.外部类访问静态内部类:先创建内部对象,再访问

    static class Inner10{
//        public int n1=2;
    private static String name="qwq";
        public void say(){
            System.out.println(Outre10.name);
            //6.如果外部类和静态内部类重名,静态内部类访问时遵循
            //就近原则,可以通过外部类.外部类成员访问外部类成员
        }
    }
    public static  Inner10 get(){
        return new Inner10();
    }
}

6.练习

s1.a=10//把默认值修改为10

s2.a=5//默认的是5

r.a=5//默认5

到此类的五大东西:属性,方法,构造器,代码块,内部类

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值