黑马程序员Java零基础视频教程(2022最新Java)B站视频学习笔记-Day14-面向对象进阶02

news/2024/5/18 16:01:02/文章来源:https://blog.csdn.net/aiains/article/details/127096336

1、权限修饰符和代码块

1.1 权限修饰符

权限修饰符:是用来控制一个成员能够被访问的范围的。

可以修饰:成员变量、方法、构造方法、内部类。

 巧计举例:

private--------私有的----------相当于私房钱,只能自己用
默认---------------------------相当于只能在家里面用
protected-------受保护的-------相当于亲戚朋友也能用
public----------公共的---------相当于全世界的人都能用

权限修饰符的使用规则

实际开发中,一般只用private和public

a、成员变量私有

b、方法公开

特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有

1.2 代码块

代码块分为三类:局部代码块、构造代码块、静态代码块。

局部代码块

作用:提前结束变量的生命周期。(技术已经被淘汰)

写在方法里面的一对大括号,作用是提前结束变量的生命周期(因为变量的作用域是外面的一层大括号的范围内)

 构造代码块

作用:抽取构造代码方法中的重复代码(不够灵活)

下面代码有两个构造方法,空参构造和全参构造,这两个构造方法中都打印了一句相同的话(打印语句在两个构造方法中重复了)此时可以把重复的代码抽取出来放在构造代码块当中

 下面是抽取后的代码:

若以后遇到在一个对象类中,构造方法并不是都有输出的时候(有的有输出,有的没有输出,此时不能用构造代码块技术),可以用以下代码来解决(用this调用其他的构造方法;或者把输出抽取成方法,然后需要的就调用)

package GouZaoDaiMaKuai;public class Student {private String name;private int age;/**构造代码块:* 1、写在成员位置的代码块,类中方法外* 2、作用:可以把多个构造方法中重复的代码抽取出来* 3、执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法*/{System.out.println("构造代码块");}public Student() {System.out.println("无参构造");}public Student(String name, int age) {System.out.println("有参构造");this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
package GouZaoDaiMaKuai;public class Test {public static void main(String[] args) {//创建对象s1(无参构造)Student s1 = new Student();//创建对象s1(有参构造)Student s2 = new Student("张三",23);}
}

输出为:

构造代码块
无参构造
构造代码块
有参构造

静态代码块(重点)

特点:适用于数据初始化,且该代码块只执行一次。

位置处于:类中方法外。

可以用来添加初始账户(即数据初始化),如下:利用静态代码块,执行App类的时候,就自动创建了一个账户,该用户可以用来直接登录

 如果用下列方法进行数据的初始化,其实是有弊端的,因为main是一个方法,main方法也是可以被调用的,每次被调用都会被添加新的重复的用户,会导致程序出现bug的。

package GouZaoDaiMaKuai;public class Student {private String name;private int age;//执行时机:随着类的加载而加载的,并且只执行一次static {System.out.println("静态代码块执行了");}public Student() {System.out.println("无参构造");}public Student(String name, int age) {System.out.println("有参构造");this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
package GouZaoDaiMaKuai;public class Test {public static void main(String[] args) {//创建对象Student s1 = new Student();Student s2 = new Student("李华",30);}
}

运行结果如下:

静态代码块执行了
无参构造
有参构造

2 抽象类

抽象类解决的问题:例如父类为Person,子类为Teacher和Student且都有work方法,但是教师和学生的工作不太一样。之前的做法是把Work方法抽取到父类Person当中,该方法的方法体只能先随便写一个,然后让子类进行重写。但是这样存在弊端,因为如果子类忘记重写Work方法,就会出现bug。为了避免这样的情况出现,可以用下面的方法对Work方法进行抽象,(抽象后的方法不用写方法体)被抽象的方法如果没有被子类重写,就会报错(即这种方法相当于在提醒开发者不要忘记重写方法)

抽象类的作用是什么?

答:抽取共性时,无法确定方法体,就把方法定义为抽象的。强制让子类按照某种格式重写。抽象方法所在的类,必须是抽象类。

抽象方法与抽象类

抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样的,所以在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。

抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类

抽象类和抽象方法的定义格式如下:

1、抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
注意:参数列表后面直接是分号,没有大括号结构体。
例如: public abstract void show(String name);2、抽象类的定义格式:
public abstract class 类名{
属性;
行为;
}例如: public abstract class Person{ 结构体 }

抽象类和抽象方法的注意事项

1、抽象类不能实例化。(实例化是指创建对象),但是可以被继承。

2、抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。

3、抽象类可以有构造方法。

4、抽象类的子类:要么重写抽象类中的所有抽象方法,要么本身(子类)也是一个抽象类。

5、抽象类的好处:

        a、可以避免父类对某个方法进行实现。

        b、子类继承父类就必须重写抽象类中的抽象方法。

6、抽象类中可以有静态方法,直接通过类名访问。

练习实践案例:编写带有抽象类的标准JavaBean类

package LianXi01;public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//因为各种动物吃的食物不一样,所以对eat方法进行抽象//抽象方法所在的类必须是抽象类,所以Animal需要改为抽象类public abstract void eat();public void dtink(){System.out.println("喝水");}
}
package LianXi01;public class Frog extends Animal{public Frog() {}public Frog(String name, int age) {super(name, age);}//父类中的抽象方法,子类必须进行重写@Overridepublic void eat(){System.out.println("吃虫子");}
}
package LianXi01;public class Dog extends Animal{public Dog() {}public Dog(String name, int age) {super(name, age);}@Overridepublic void eat(){System.out.println("吃骨头");}
}
package LianXi01;public class Sheep extends Animal{public Sheep() {}public Sheep(String name, int age) {super(name, age);}@Overridepublic void eat(){System.out.println("吃草");}
}
package LianXi01;public class test {public static void main(String[] args) {//创建对象Frog f = new Frog("小绿",1);System.out.println(f.getName()+","+f.getAge());f.eat();f.dtink();}
}

运行结果如下:

小绿,1
吃虫子
喝水

补充内容:模板设计模式

1、设计模式:是一种反复使用,多人知晓,经过分析编译代码、代码设计经验的总结。

2、使用设计模式的目的:为了让代码更容易被别人理解,保证代码的可靠性和程序的重用性。

3、模板设计模式:把抽象类整体看作一个模板,模板中不能决定的内容使用抽象方法表示,让使用模板的类【抽象类的子类】去重写抽象方法,实现需求。

4、好处:模板设计模式优势在于,已经设定好通用的结构,使用者只需要直接拿着去用就可以了,只需要关注自己实现的内容即可。

3 接口

3.1、为什么要有接口?

例如下面:如果定义游泳行为,因为兔子不会游泳,所以游泳行为不可以抽取到父类当中,然而在子类当中各自单独定义游泳行为的时候,方法名可能出现方法不统一的现象(例如下面的swim和swimming方法),为了解决这个问题,接口就出现了。接口就是一种规则。

创建一个接口(相当于创建一种规则),在接口中就能定义游泳的抽象方法,然后让青蛙类和狗类重写接口中的swim方法。

 接口的应用:接口不代表一类事务,它是一种规则,它是对行为的抽象。

 

3. 2、接口的定义和使用

(1)、接口用关键字interface来定义。

public interface 接口名 {}

(2)、接口不能实例化。

(3)、接口和类之间是实现关系,通过implements关键字表示

public class 类名 implements 接口名 {}

(4)、接口的子类(实现类):要么重写接口中的所有抽象方法,要么是抽象类。

(5)、接口中的方法都是抽象方法。

注意事项:

接口的创建流程:右击包名,选择新建Java类,然后不选class,而是选择Interface,然后回车。

 练习实践案例:编写带有接口和抽象类的标准JavaBean类

父类代码:

package LianXi01;public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public abstract void eat();}

接口代码:

package LianXi01;public interface Swim {     //接口public abstract  void swim();   //接口中的抽象方法
}

兔子类代码:

package LianXi01;public class Rabbit extends Animal{public Rabbit() {}public Rabbit(String name, int age) {super(name, age);}@Overridepublic void eat(){System.out.println("兔子在吃胡萝卜");}
}

青蛙类代码:

package LianXi01;public class Frog extends Animal implements Swim{public Frog() {}public Frog(String name, int age) {super(name, age);}//父类中的抽象方法,子类必须进行重写@Overridepublic void eat(){System.out.println("青蛙在吃虫子");}@Overridepublic void swim() {System.out.println("青蛙在蛙泳");}
}

狗类代码L:

package LianXi01;public class Dog extends Animal implements Swim{public Dog() {}public Dog(String name, int age) {super(name, age);}//父类中的方法和接口中的方法可以利用快捷方式同时添加重写//当implements处报错的时候,按住alt+enter,选择implement methods选项//然后crlt+A,全选,最后点击回车确认即可@Overridepublic void eat(){System.out.println("狗吃骨头");}@Overridepublic void swim() {System.out.println("狗刨");}
}

测试类代码:

package LianXi01;public class test {public static void main(String[] args) {//创建对象Frog f = new Frog("小绿",1);System.out.println(f.getName()+","+f.getAge());f.eat();f.swim();System.out.println("-----------");Rabbit r = new Rabbit("小白",3);System.out.println(r.getName()+","+r.getAge());r.eat();//r.swim();    r调用不了swim方法,因为兔子类没有调用游泳接口}
}

输出结果如下:

小绿,1
青蛙在吃虫子
青蛙在蛙泳
-----------
小白,3
兔子在吃胡萝卜

3.3 接口中成员的特点

 3.4 接口和类之间的关系

(1)、类和类的关系:继承关系,只能单继承,不能多继承,但是可以多层继承。

(2)、类和接口的关系:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。

接口1代码

package ChengYuanTeDian;public interface Inter1 {public abstract void method1();public abstract void method2();public abstract void method3();
}

接口2代码

package ChengYuanTeDian;public interface Inter2 {public abstract void method1();public abstract void method2();public abstract void method3();public abstract void method4();
}

创建一个实现类,调用两个接口

package ChengYuanTeDian;public class Intermpl implements Inter1,Inter2{//当两个接口中有重复的方法时,只需要重写一次即可//例如下面案例中,method1,method2,method3在Inter1、Inter2中都有//但下面案例中就重写了一次@Overridepublic void method1() {System.out.println("method1");}@Overridepublic void method2() {System.out.println("method2");}@Overridepublic void method3() {System.out.println("method3");}@Overridepublic void method4() {System.out.println("method4");}
}

测试类代码

package ChengYuanTeDian;public class Test {public static void main(String[] args) {System.out.println();}
}

(3)、接口和接口的关系:继承关系,可以单继承,也可以多继承。(如果实现类实现的是最下面的子接口的话,那么就需要重写所有的抽象方法)

接口1代码

package ChengYuanTeDian;public interface Inter1 {public abstract void method1();
}

接口2代码

package ChengYuanTeDian;public interface Inter2 {public abstract void method2();
}

接口3代码(继承了接口1和接口2)

package ChengYuanTeDian;public interface Inter3 extends Inter1,Inter2{public abstract void method3();
}

接口的实现类代码

package ChengYuanTeDian;public class Intermpl implements Inter3{//由于接口3继承了接口2和接口1,所以实现类实现接口3的时候,接口1和接口2中的方法也必须得重写。@Overridepublic void method3() {}@Overridepublic void method1() {}@Overridepublic void method2() {}
}

测试类代码

package ChengYuanTeDian;public class Test {public static void main(String[] args) {System.out.println();}
}

3.5 综合练习

综合案例1:编写带有接口和抽象类的标准JavaBean类。

我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口?

 思路1

 思路2:

通过思路2进行代码书写

Person类代码如下:

package JieKouLianXi;
//因为现在我不想让外界直接创建人的对象
//因为直接创建顶层父类人的对象此时是没有意义的
//所以我就把他写为抽象的
public abstract class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

运动员类代码如下:

package JieKouLianXi;public abstract class YunDongYuan extends Person{public YunDongYuan() {}public YunDongYuan(String name, int age) {super(name, age);}//因为学习的内容不一样,所以study定义为抽象的方法public abstract void study();
}

教练类代码如下:

package JieKouLianXi;public abstract class JiaoLian extends Person{public JiaoLian() {}public JiaoLian(String name, int age) {super(name, age);}//因为教练教的内容不一样,所以teach定义为抽象的方法public abstract void teach();
}

接口代码如下:

package JieKouLianXi;public interface English {public abstract void speakEnglish();
}

乒乓球运动员类代码如下:

package JieKouLianXi;
//乒乓球运动员继承父类运动员,调用接口学英语
public class PingPangYDY extends YunDongYuan implements English{//一定不要忘记构造方法的书写public PingPangYDY() {}public PingPangYDY(String name, int age) {super(name, age);}//重写接口中的方法@Overridepublic void speakEnglish() {System.out.println("乒乓球运动员在说英语");}//重写父类中的抽象方法@Overridepublic void study() {System.out.println("乒乓球运动员在学习如何打乒乓球");}
}

篮球运动员类代码如下:

package JieKouLianXi;public class LanQiuYDY extends YunDongYuan{public LanQiuYDY() {}public LanQiuYDY(String name, int age) {super(name, age);}@Overridepublic void study() {System.out.println("蓝球运动员在学习如何打篮球");}
}

乒乓球教练类代码如下:

package JieKouLianXi;public class PingPangQiuJL extends JiaoLian implements English{public PingPangQiuJL() {}public PingPangQiuJL(String name, int age) {super(name, age);}@Overridepublic void speakEnglish() {System.out.println("乒乓球教练在说英语");}@Overridepublic void teach() {System.out.println("乒乓球教练在教运动员打乒乓球");}
}

篮球教练类代码如下:

package JieKouLianXi;public class LanQiuJL extends JiaoLian{public LanQiuJL() {}public LanQiuJL(String name, int age) {super(name, age);}@Overridepublic void teach() {System.out.println("蓝球教练在教运动员打篮球");}
}

测试类代码如下:

package JieKouLianXi;public class Test {public static void main(String[] args) {PingPangYDY ppydy = new PingPangYDY("李华",24);System.out.println(ppydy.getName()+","+ppydy.getAge());ppydy.study();ppydy.speakEnglish();}
}

输出结果如下:

李华,24
乒乓球运动员在学习如何打乒乓球
乒乓球运动员在说英语

3.6 多学三招:

(1)、JDK8开始接口中新增加的方法

JDK7以前:接口中只能定义抽象方法。

JDK8的新特性:接口中可以定义有方法体的方法。(默认、静态)

A、接口中定义有方法体的默认方法。

 实践案例如下:

package JieKou;public interface InterA {/**接口中的默认方法* 定义格式:public default 返回值类型 方法名(参数列表){  }** 接口中默认方法的注意事项:* 1、默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字* 2、public可以省略,default不能省略* 3、如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写*///定义抽象方法public abstract void method();//定义默认方法public default void show(){System.out.println("InterA接口中的默认方法------show");}
}
package JieKou;public interface InterB {//定义默认方法public default void show(){System.out.println("InterB接口中的默认方法------show");}
}
package JieKou;public class Intermpl implements InterA ,InterB{//默认方法不是抽象方法,所以不强制被重写@Overridepublic void method() {System.out.println("实现类重写的抽象方法");}//在实现类中,书写接口中的默认方法的时候,可以利用快捷方式:方法名+回车//当接口实现类同时调用接口A和接口B的时候,show方法必须要重写,不然测试类Test创建对象后,调用//show方法的时候分不清调用的是接口A中的还是接口B中的,此时就会报错//然而重写show方法之后,测试类中调用的show方法是重写后的@Overridepublic void show() {System.out.println("重写接口中的默认方法");}
}
package JieKou;public class Test {public static void main(String[] args) {Intermpl ii = new Intermpl();ii.method();ii.show();}
}

运行结果如下:

实现类重写的抽象方法
重写接口中的默认方法

B、接口中定义有方法体的静态方法。

实践案例如下:

package JieKou;public interface Inter {//定义一个抽象方法public abstract void menoth();//定义静态方法public static void show(){System.out.println("InterA接口中的静态方法");}
}
package JieKou;public class Intermpl implements Inter {@Overridepublic void menoth() {System.out.println("Intermpl重写的抽象方法");}//静态方法不能被重写,如果重写,系统就会报错//下面不是show方法的重写,因为静态方法不能被重写,此处只是定义了一个和接口中具有同名的静态方法而已public static void show(){System.out.println("实现类中的静态方法");}
}
package JieKou;public class Test {public static void main(String[] args) {//调用接口中的静态方法,调用格式: 接口名.方法名();Inter.show();//调用实现类中的静态方法,调用格式:实现类名字.方法名();Intermpl.show();/**重写的概念* 子类把从父类继承下来的虚方法表里面的方法进行覆盖了,这才叫重写。* 注意:静态的、私有的、最终的是不会被添加到虚方法表里面的,因此这三类不能被重写*/}
}

运行结果如下:

InterA接口中的静态方法
实现类中的静态方法

JDK9的新特性:接口中可以定义私有方法。

私有方法分为两种:普通的私有方法,静态的私有方法

普通的私有方法是给默认方法使用的,静态的私有方法是给静态方法使用的。

 实践案例如下:

 

(2)、接口的应用

方式1:

 方式2:

 接口的应用(小结):

1、接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。

2、当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。

(3)、适配器设计模式

 实践案例如下:

package Dome;public interface Inter {public abstract void method1();public abstract void method2();public abstract void method3();public abstract void method4();public abstract void method5();public abstract void method6();public abstract void method7();public abstract void method8();public abstract void method9();public abstract void method10();
}
package Dome;
//创建一个适配器调用接口,然后对接口中所有的方法进行空实现
//空实现是指:实现了,但是方法体不写,让方法体空着
//因为适配器对接口中的所有方法进行了空实现,所以外界调用适配器没有意义,因此适配器应改为抽象类
public abstract class InterAdapter implements Inter{@Overridepublic void method1() {}@Overridepublic void method2() {}@Overridepublic void method3() {}@Overridepublic void method4() {}@Overridepublic void method5() {}@Overridepublic void method6() {}@Overridepublic void method7() {}@Overridepublic void method8() {}@Overridepublic void method9() {}@Overridepublic void method10() {}
}
package Dome;public class Intermpl extends InterAdapter{//需要用到哪个方法,就重写哪个方法就可以了@Overridepublic void method5() {System.out.println("只要用第五个方法");}
}
package Dome;public class Test {public static void main(String[] args) {Intermpl m1 = new Intermpl();m1.method5();}
}

运行结果如下:

只要用第五个方法

适配器设计模式(小结)

A、当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器设计模式。

B、书写步骤如下:

        a、编写中间类XXXAdapter,实现对应的接口。

        b、对接口中的抽象方法进行空实现。

        c、让真正的实现类继承中间类,并重写需要用的方法。

        d、为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰。

C、如果真正的实现类还有一个父类H,但是Java中不能多继承,此时让中间类XXXAdapter去继承父类H就能解决此问题。(即让真正的子类与父类H实现间接继承)

4 内部类

4.1、什么是内部类?

类的五大成员:属性、方法、构造方法、代码块、内部类。

内部类的定义:在一个类里面,再定义一个类。

 

package LianXi;public class Car {String carName;int carAge;String carColor;public void show2(){//System.out.println(carName);//外部类要访问内部类成员,必须创建内部类对象Engine e = new Engine();    //创建内部类对象//e.engineName = "汽车引擎";//e.show();System.out.println(e.engineName);   //如果不创建内部类对象,这个输出就会报错}//定义内部类class Engine{String engineName;int engineAge;public void show(){ //内部类可以直接访问外部类的成员,包括外部类的私有成员System.out.println(engineName);System.out.println(carName);}}}
package LianXi;public class Test {public static void main(String[] args) {Car c = new Car();c.carName = "宾利";c.carAge = 1;c.carColor = "黑色";c.show2();}
}

4.2、内部类的分类

成员内部类静态内部类局部内部类,这三个只做了解,匿名内部类需要重点掌握。

4.2.1 成员内部类:

A、成员内部类的代码如何书写?以及编写成员内部类的注意点

        a、定义:写在成员位置的,属于外部类的成员

        b、成员内部类可以被一些修饰符所修饰,比如:private、默认、protected、public、static等

        c、在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。

        d、内部类可以访问外部类中的所有成员,包括私有成员。

        e、外部类中访问内部类中的成员,必须创建内部类对象。

B、如何创建成员内部类的对象?(获取成员内部类对象的两种方式)

方式1:当成员内部类被private修饰时。在外部类中编写方法,对外提供内部类的对象。

方式2:当成员内部类被非私有修饰时,直接创建对象。直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

方式2:
Outer.Inter oi = new Outer().new Inter();

实践案例代码如下:

package LianXi;public class Outer {String name;//定义内部类private class Inter{}//当内部类被私有化时,让外部类Outer编写方法,对外提供内部类对象public Inter getInstance(){return new Inter();}
}
package LianXi;public class Test {public static void main(String[] args) {//1、如果内部类没有被私有化,则可以直接创建对象//直接创建对象的格式如下://Outer.Inter oi = new Outer().new Inter();//2、当内部类被私有化的时候,只能通过下面的方式创建内部类//2.1、先创建外部类对象Outer o = new Outer();//再调用外部类中的getInstance()方法获取到创建内部类对象,并赋值给变量iiObject ii = o.getInstance();//2.2、或者直接利用输出语句输出o.getInstance()System.out.println(o.getInstance());}
}

C、成员内部类如何获取外部类的成员变量?

package LianXi;public class Outer {private int a = 10;//定义内部类class Inter{private int a = 20;public void show(){/**变量的调用* 调用内部类中的方法中的变量:变量名  比如:a* 调用内部类中方法外的变量:this.变量名  比如:this.a* 调用外部类的变量:外部类类名.this.变量名  比如:Outer.this.a*/int a = 30;System.out.println(a);  //30System.out.println(this.a);    //20System.out.println(Outer.this.a);   //10}}
}
package LianXi;public class Test {public static void main(String[] args) {//创建内部类的对象,并调用内部类中的show方法Outer.Inter oi = new Outer().new Inter();oi.show();}
}

输出结果如下:

30
20
10

4.2.2 静态内部类

静态内部类只能访问外部类中静态变量静态方法,如果想要访问非静态的需要创建外部类的对象

访问特点:

1、是外部类的静态成员,可以直接通过类名去访问,而不需要创建外部类对象。

2、静态内部类的非静态成员,需要等所在的内部类对象创建之后,才能被调用。

3、一个类是否需要创建对象,不取决于该类是否是静态,而是取决于要访问的成员是否是静态。

静态内部类访问外部类,实践案例代码如下:

package LianXi;public class Outer01 {int a = 10;static int b = 20;//静态内部类static class Inter{public void show1(){System.out.println("非静态的方法被调用了");//System.out.println(a);  语句会报错,因为静态内部类只能访问外部类中//的静态变量和静态方法,而不能访问外部类中非静态变量和静态方法System.out.println(b);}public static void show2(){System.out.println("静态的方法被调用了");//如果想要访问外部类中非静态的,需要创建外部类的对象Outer01 o = new Outer01();System.out.println(o.a);}}
}

外部类访问静态内部类,实践案例代码如下:

package LianXi;public class Outer02 {//创建静态内部类static class Inter002{public void work(){System.out.println("非静态的方法被调用了");}public static void work2(){System.out.println("静态的方法被调用了");}}
}
package LianXi;public class Test {public static void main(String[] args) {//调用非静态方法时,先创建对象,用对象调用//创建静态内部类对象的格式:// 外部类名.内部类名 对象名 = new 外部类名.内部类名();Outer02.Inter002 oi02 = new Outer02.Inter002();oi02.work();//调用静态方法时,直接调用,格式://  外部类名.内部类名.方法名();Outer02.Inter002.work2();}
}

运行结果如下:

非静态的方法被调用了
静态的方法被调用了

4.2.3 局部内部类

1、将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。

2、外界是无法直接使用,需要在方法内部创建对象并使用

3、该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

4、能修饰局部变量的都能用来修饰局部内部类,不能修饰局部变量的就不能修饰局部内部类。

实践案例代码如下:

package LianXi;public class Outer01 {int b = 20;public void show(){int a = 10;//局部内部类class Inter{String name;int age;//定义一个方法public void method1(){System.out.println(a);  //该类可以直接访问方法内的局部变量 10System.out.println(b);  //该类可以直接访问外部类的成员 20System.out.println("局部内部类中的method1方法");}/*//局部内部类中,不能定义静态方法,会报错public static void method2(){System.out.println("局部内部类中的method2方法");}*/}//外界是无法直接使用局部内部类的,需要在方法内部创建对象并使用//创建局部内部类的对象Inter i = new Inter();//此处会调用构造方法,而method1()不是构造方法System.out.println(i.name); //nullSystem.out.println(i.age);  //0i.method1();    //调用method1方法,打印方法中的三个输出}
}
package LianXi;public class Test {public static void main(String[] args) {//调用show方法,让代码执行Outer01 o = new Outer01();o.show();   //局部内部类在show方法中,执行show方法就执行了内部类}
}

运行代码如下:

null
0
10
20
局部内部类中的method1方法

4.2.4 匿名内部类

实践案例代码如下:

package NiMing;public interface Swim {public abstract void swim();
}
package NiMing;public abstract class Animal {public abstract void eat();
}
package NiMing;public class Test {public static void main(String[] args) {System.out.println();//编写匿名内部类的代码,此处相当于new(创建)了Swim的实例化对象(实例化)//接口实例化的过程中需要书写接口中所有的抽象方法new Swim(){@Overridepublic void swim() {System.out.println("重写了游泳的方法");}};//编写匿名内部类的代码,此处相当于new(创建)了Animal的子类对象(继承)//继承的过程中,子类需要重写父类中所有的抽象方法new Animal(){@Overridepublic void eat() {System.out.println("重写了eat方法");}};//执行静态方法,相当于method(参数);  参数为对象(此处对象指匿名内部类)method(new Animal(){@Overridepublic void eat() {System.out.println("狗吃骨头");}});}//创建静态方法public static void method(Animal a){a.eat();}}

小结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_23977.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVS+KeepAlived高可用负载均衡集群

内容预知 1. 高可用群集的相关知识 1. 1 高可用(HA)群集与普通群集的比较 普通群集 高可用群集(HA) 1.2 KeepAlive 高可用方案 1.3 KeepAlived的体系模块 1.4 Keepalived实现原理 2. 高可用群集的脑裂现象及预防措施 2.1 高可用集群的脑裂现象及其…

树莓派学习笔记

记录一下树莓派的使用,包含操作系统、linux命令、python、硬件等知识。参考《树莓派开发实战》树莓派简介及型号 树莓派(Raspberry Pi)是一款基于 Linux 系统的、只有一张信用卡大小的卡片式计算机,树莓派已经成为基于 Linux 的低成本电脑和嵌入式计算机平台这个领域中的重…

Material UI – React (2022) 版的完整教程

Material UI – React (2022) 版的完整教程 这是关于 Material UI 的最期待的课程。该课程涵盖了 Material UI 的所有组件 课程英文名:Material UI - The Complete Guide With React (2022) Editio 此视频教程共5.5小时,中英双语字幕,画质…

【贝塞尔曲线拟合】

贝塞尔曲线拟合问题描述拟合曲线生成过程参考程序注意事项问题描述 已知一条n阶贝塞尔曲线L(P0,P1,P2,P3,...,Pn)L(P0, P1, P2, P3, ..., Pn)L(P0,P1,P2,P3,...,Pn)(P0P0P0为起点,P1P1P1为第一个控制点,P2P2P2为第二个控制点,P3P…

Mysql删除重复数据只保留一条

(1)以这张表为例: CREATE TABLE test (id varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 注解id,name varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 名字,PRIMARY KEY…

队列的顺序存储结构

说白了,就是一个数组 ,然后在两端进行操作 ,两端用首队指针和尾指针分别指向 ,然后进行相关的删除,插入操作, 目的还是模拟现实对数据的处理 ●描述队列 •数据元素data , 元素具有同一类型ElemType ,最多为MaxSize(数组容量) •当前队首front •当前队尾 rear 定义队列的数据…

RK3588安装部署openmediavault

RK3588安装部署openmediavault部署准备Debian 10 文件系统编译和获取安装 openmediavault安装基础依赖安装 openmediavault 原秘钥环添加 openmediavault 官方原安装 openmediavault 基础依赖安装 openmediavaultopenmediavault 相关资料: https://docs.openmediav…

YOLOX 学习笔记

笔记来源:https://www.bilibili.com/video/BV1jo4y1D7CF/?vd_source2ed6e8af02f9ba8cb90b90e99bd4ccee 近年来,目标检测的工程应用研究中,YOLO系列以快速响应、高精度、结构简单以及容易部署的特点备受工程研究人员的青睐。同时,…

3. HDFS分布式文件系统

3.1 HDFS简介 随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布…

CloudlaC是什么?

目录1. CloudIaC的简介2. 部署安装2.1 下载并解压安装包2.2 安装并启动Docker2.3 安装并启动Mysql2.4 安装并启动 Consul2.5 编辑配置文件2.6 初始化MySQL2.7 安装iaC服务2.8 启动 IaC 服务2.9 拉取 ct-worker 镜像2.10 下载前端部署包并解压2.11 安装nginx并配置2.12 访问web页…

【笔试刷题训练】day_04

选择题 C/C中各种进制的表示方法 二进制:在数字的末尾加b,如101010b 八进制:在数字前面加数字0,如0123 十进制:数字本身,如123 十六进制:数字前面加0x 或者 数字后面加h,如0x123、12…

字节跳动C++云原生二面(65min)

字节跳动C云原生二面(65min) 面试问题 HTTP1.0 、1.1和2.0 的区别和差异是什么 《HTTP1.0和1.1的区别》HTTP1.1 默认开启长连接(keep-alive) 而HTTP1.0需要添加参数,在一定程度上减少了建立和关闭连接的消耗和延迟HT…

AntDesign-Vue Table 查询与分页

前言 之前的增删改查小 Demo 已经快要进行到最后一步了,这节的任务是将请求数据的方式改为 分页,并且增加 分页条件查询 的功能。 页面布局 <a-table:data-source="dataSource":columns="columns":pagination="pagination" > <!-- ↑…

02 docker安装

这里写目录标题CenterOS安装使用远程镜像仓库安装设置yum远程仓库第二步&#xff1a;安装docker安装第三步&#xff1a;docker镜像加速器debian/Ubuntu安装docker官网&#xff1a;https://www.docker.com/ docker镜像库&#xff1a;https://hub.docker.com/ Docker CE&#xf…

truffle安装问题-无法加载文件

在powershell 下输入以下命令 set-executionpolicy remotesigned问题解决搜索 复制

【C语言】文件版本通讯录

文章目录文件版本通讯录一、test.c&#xff08;通讯录主干&#xff09;1.通讯录菜单的实现2.创建通讯录&#xff0c;初始化通讯录3.通讯录功能的调用二、contact.c(函数的实现)1.通讯录初始化2.查看联系人是否存在函数实现3.单个修改联系人各项的信息函数实现4.修改联系人信息目…

【PyTorch深度学习项目实战100例】—— 基于Transformer实现Twitter文本隐喻二分类 | 第43例

前言 大家好,我是阿光。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPy…

[Vue] TodoList 案例

前言 系列文章目录&#xff1a; [Vue]目录 老师的课件笔记&#xff0c;不含视频 https://www.aliyundrive.com/s/B8sDe5u56BU 笔记在线版&#xff1a; https://note.youdao.com/s/5vP46EPC 视频&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 文章目录前言1. 组件…

《uni-app》一个非canvas的飞机对战小游戏实现-敌机模型实现

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e;接下来的几篇都是uni-app的小实战&#xff0c;有助于我们更好的去学习u…

行业大洗牌,软件测试饱和了?到底怎样才能走出职场困境......

人生三大emo瞬间&#xff1a;工作不顺&#xff0c;薪资不涨&#xff0c;求职被拒。 都说成年人的世界里没有容易二字&#xff0c;这句话在职场里体现地淋漓尽致&#xff1a; 工作5年&#xff0c;还没来得及升职&#xff0c;薪资被倒挂&#xff0c;岗位被优化&#xff1b;晚上…