初识面向对象
思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,然后对这些分类进行单独思考,最后,才对某个分类下的细节进行面向过程的思考
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
- 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
- 面向对象的本质就是:以类的方式组织代码,以对象的形式组织(封装)数据*
- 抽象
- 特性:封装、继承、多态
- 从认识的角度思考是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
- 从代码运行角度考虑是先有类后有对象,类是对象的模板。
public class OopDemo1 {
public static void main(String[] args) {
//创建Cat对象
//cat1是对象名(对象引用)
//new Cat() 创建的对象空间(数据),才是真正的对象
Cat cat1 = new Cat();
cat1.age = 5;
System.out.println(cat1.age);
cat1.say();
}
//对象的属性默认值,遵守数组规则
//默认值:int 0,short 0, byte 0, long 0, float 0.0, double 0.0, char \u0000, boolean false,String null;
//当不进行初始化赋值时,都是默认初始化值
}
class Cat{
String name;//属性
int age;//属性
String color;//属性
public void say(){//行为
System.out.println("叫了一声");
}
}
对象的创建
- 类是一种抽像的数据类型,他是对某一类事物整体描述/定义,但是并不能代表某一个事物的具体的事物
- 成员变量 = 属性 = field(字段)
- 属性是类的一个组成部分,一般是基本数据类型,也是引用类型(对象,数组)。比如定义一个猫类的int age 就是属性
- 先声明在创建
Cat cat;//声明对象cat
cat = new Cat();//创建
- 直接创建
Cat cat = new Cat();
- 对象是抽象概念的具体的实例
- 使用new关键字创建对象
- 使用new关键字创建对象的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构建器的调用
- 类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 构造器必须要掌握
封装
-
把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作
-
封装的好处和理解
- 隐藏实现细节
- 可以对数据进行验证,保证安全合理
-
该漏的漏,该藏的藏
- 程序设计要追求”高内聚,低耦合“。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口有来访问,这称为信息隐藏
-
属性私有,get(获取属性的值)/set(判断属性并赋值)
-
/*1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.增加了系统的可维护性 */
继承
- 继承的本质是对某一批类的抽象,从而事项对现实世界更好的建模
- 继承可以解决代码复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可
- extends的意思是“扩展”。子类是父类的拓展,继承后子类自动拥有父类定义的属性
- 继承所带来的便利:
- 代码的复用性提高了
- 代码的拓展性和维护性提高了
细节
- 子类继承了所有的属性和方法,但是私有属性不能再子类直接访问,要通过公共的方法去访问
- 子类必须调用父类的构造器,完成父类的初始化
- 当创建对象时,不管使用子类的那个构造器,则必须再子类的构造器中用super去指定使用父类的那个构造器完成对付类的初始化工作,否则,编译不会通过,如果父类中没有写构造器,则默认调用无参构造器,如果父类中写了有参构造器,则必须在子类的构造器中写明调用的是父类的那个构造器
- 如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表)
- super在使用时,需要放在构造器第一行
- super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
- java所有类都是Object类的子类
- 父类构造器的调用不限于直接父类!将一直网上追溯知道Object类(顶级父类)
- 子类最多只能继承一个父类(直接继承),即Java中式但继承机制
- 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
- Java中只有单继承没有多继承
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
public class Test {
public static void main(String[] args) {
Son son = new Son();//内存的布局
//这时应该注意,要按照查找关系来返回信息
//1.首先看子类是否有该属性
//2.如果子类有这个属性,并且可以访问,则返回信息
//3.如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)
//4.如果父类没有按照3.的规则,继续招商及父类,知道Object
System.out.println(son.name);
System.out.println(son.age);
System.out.println(son.hobby);
}
}
class Son extends Father{
String name = "大头儿子";
}
class Father extends GrandePa{
String name = "大头爸爸";
int age = 53;
}
class GrandePa {
String name = "大头爷爷";
String hobby = "旅游";
}
- object类
public class Person {
public Person() {
System.out.println("Person无参执行了");
}
protected String name = "shenghao";
//public 公共的 优先级最高
//protected 受保护的
//default 默认的
//private 私有的 优先级最低
private int money = 1000;
public void say() {
System.out.println("shuojuhua");
}
public void print(){
System.out.println("Person");
}
//私有的方法无法被继承
public int getMoney() {
return this.money;
}
public void setMoney(int money) {
this.money = money;
}
}
//学生 : 派生类 子类
//子类继承了父类,就会拥有父类的全部方法
public class Student extends Person{
public Student() {
//隐藏代码,调用了父类的无参构造
super();//调用父类的构造器,必须压迫在子类构造器的第一行
System.out.println("Student无参执行了");
}
private String name = "sheng";
public void print(){
System.out.println("Student");
}
public void test1(){
print();
this.print();
super.print();
}
public void test(String name){
System.out.println(name);//盛浩
System.out.println(this.name);//sheng
System.out.println(super.name);//shenghao
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
Person p1 = new Person();
student.say();
student.setMoney(100);
System.out.println(student.getMoney());
student.test("盛浩");
student.test1();
}
package Test2;
/*
编写Computer类,包含CPU,内存,硬盘等属性,getDetails方法用于返回Computer的详细信息
编写PC子类,继承Computer类,添加特有属性[品牌brand]
编写NotePad子类,继承Computer类,添加特有属性[演示color]
编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法打印输出信息
*/
public class Computer {
public String cpu;//芯片
public int memory;//内存
public String hard;
public Computer(String cpu,int memory,String hard){
this.hard = hard;
this.memory = memory;
this.cpu = cpu;
}
public String getDetails(){
return "cpu:"+cpu+" memory:"+memory+" hard:"+hard;
}
}
class PC extends Computer{
//编写PC子类,继承Computer类,添加特有属性[品牌brand]
public String brand;//品牌
public PC(String brand,String cpu,int memory,String hard){
super(cpu,memory,hard);
}
public void showInfo(){
System.out.println("品牌"+brand+getDetails());
}
}
class NotePad extends Computer{
//编写NotePad子类,继承Computer类,添加特有属性[演示color]
public String color;
public NotePad(String color,String cpu,int memory,String hard){
super(cpu,memory,hard);
}
public void showInfo(){
/*
找getDetails的方法时(getDetails()和this.getDetails())的顺序是:
首先找本类,如果有,则调用
再找父类,如果有,则调用
父类找不到,继续往上找,一直到Object类
提示:在查找方法的过程中,如果找不到,则提示方法不存在
在查找方法的过程中,如果找到了,但是不能访问,则报错
this.方法名:从本类开始找
super.方法名:从父类开始找
*/
System.out.println(getDetails()+"颜色:"+color);
}
}
//编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,
// 以及从Computer类继承的属性赋值,并使用方法打印输出信息
public class ComTest {
public static void main(String[] args) {
PC pc = new PC("华为","rtx4090",1024,"C盘");
NotePad notePad = new NotePad("white","rtx4090t",1024,"d盘");
pc.showInfo();
notePad.showInfo();
}
}
-
super
-
调用父类的构造器,必须压迫在子类构造器的第一行
-
访问父类的属性,但不能访问父类的private属性 super.属性名
-
访问父类的方法,不能访问父类的private方法 super.方法名(参数列表)
-
调用父类的构造器的好处,(分工明确,父类属性由父类初始化,子类属性有子类初始化)
-
当子类中有父类的成员(属性和变量)崇明是,为了访问父类的成员,必须通过super。如果没有重名,使用super,this,直接访问是一样的效果
-
super的访问不限于直接父类,如果父类的父类和本类也有同名的成员,也可以使用
-
super去访问爷爷类的成员,如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则
-
访问父类的构造器
- super(参数列表);只能放在构造器的第一句!
-
super注意点: 1.super调用父类的构造方法,必须在构造方法的第一行 2.super必须只能出现在子类的方法或者构造方法中 3.super和this不能同时调用构造方法 vs this: 代表的对象不同: this:本身调用者这个对象 super:代表父类对象的应用 前提 this:没有继承也可以使用 super :只能在继承条件下才可以使用 构造方法: this();本类的构造 super();父类的构造
-
-
方法重写
- 基本介绍:
- 简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称,返回类型,参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法
- 方法重写也叫方法覆盖,需要满足下面的条件
- 子类的方法的形参列表,方法名称要和父类方法的参数,方法名称完全一样。
- 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
- 子类方法不能缩小父类方法的访问权限 public >protected>默认>private,父类如果是public,子类就不能是peotected
- 基本介绍:
public class A extends B{
//Override重写
@Override//注解:有功能的注释!
public void test() {
System.out.println("A=>test()");
}
}
//重写都是方法的重写,和属性无关
public class B {
public void test() {
System.out.println("B=>test()");
}
}
public class Application1 {
public static void main(String[] args) {
//静态方法和非静态方法区别很大
//静态方法: 方法的调用之和左边,定义的数据类型有关
//非静态:重写
A a = new A();
a.test();//A
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//B
}
}
/*
重写:需要有继承关系,子类重写父类的方法
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大:public > protected > default > private
4.抛出的异常:范围,可以被缩小,但不能扩大:
重写,子类的方法和父类必须要一直,方法体不同
为什么要重写:
1.弗雷德功能,子类不一定需要,或者不一定满足
*/
多态
- 同一方法可以根据发送对象的不同而采取多种不同的行为方式
- 方法或对象具有多种形态,是面向对象的第三大特征,多条是建立在封装和继承基础之上的
- 一个对象的实际类型是确定的,单可以指向对昂的引用类型有很多(父类,有关系的类)
- 多态的具体体现:
- 方法的多态 重新二和重载就体现多态
- 对象的多态:
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义是 等号的左边,运行类型看等号的右边
- 注意:多态是方法的多态,属性没有多态性
- 前提:两个对象(类)存在继承关系
- 多态的向上转型
- 本质:父类的引用指向了子类的对象
- 语法:父类类型 引用名 = new子类类型();
- 特点:编译类型看左边,运行类型看右边
- 可以调用父类中的所有成员,需要遵循访问权限,不能调用子类中的特有成员,最终运行效果看子类的具体实现
- 多态向上转型调用方法的规则如下:
- 可以调用父类中的所有成员(须遵循访问权限)
- 但是不能掉哟个子类的特有的成员
- 因为在编译阶段,能调用那些成员,是由编译类型来决定的
- 最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法
- 然后调用,跟方法调用的规则一致
- 多态向下转型:
- 语法:子类类型 引用名 = (子类类型)父类引用;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的时当前忙于表类型的对象
- 向下转型后可以调用子类类型中所有的成员
public class Person {
public void run(){
System.out.println("run");
}
}
/*
多态注意事项:
1.多态是方法的多态,属性没有多态
2.子类和父类,有联系 类型转换异常 ClassCastException!
3.存在条件: 继承关系,方法要重写,父类引用指向子类对象!Father f1 = new Son();
无法被重写的方法:
1.static 方法,属于类,它不属于实例
2.final 常量
3.private方法
*/
public class Student extends Person{
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("eee");
}
public void go(){
System.out.println("go");
}
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
// Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行那些方法,主要看对象左边的类型,和右边那关系不大!
//如果这个方法只有父类有,那么父类和子类都可以调用
//如果这个方法只有子类有,则父类需要强制类型转换后才可以调用
//如果这个方法,父类和子类都有的情况下,但是输出的结果不同,优先调用子类的
s2.run();//子类重写了父类的方法,执行了子类的方法
s1.run();
((Student)s2).eat();//强制类型转换
}
}
-
属性没有重写之说,属性的值看编译类型
-
public class A {//父类 public int count = 10;//属性 } class B extends A{//子类 public int count = 20;//属性 }
-
public class Test1 { public static void main(String[] args) { A a = new B();//向上转型 System.out.println(a.count);//10,跟编译类型有关,和运行类型无关 B b = new B(); System.out.println(b.count);//20,编译类型时B, } }
-
instanceof(类型转换)引用类型:用于判断对象的运行类型是否位xx类型或xx类型的子类型
public class Application1 {
public static void main(String[] args) {
//Object > Person > Student
//Object > Person > Teacher
//Object > String
Object object = new Student();
//System.out.println(X instanceof Y); //能不能编译通过,主要看X跟Y有没有父子关系
//创建对象是以子类
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
//Teacher是Person的另一个子类,跟Student不存在继承关系,所以输出的结果是false
System.out.println(object instanceof Teacher);//false
//Sting类是Object的一个子类,与Student不存在继承关系
System.out.println(object instanceof String);//false
System.out.println("=======================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
//Teacher是Person的另一个子类,跟Student不存在继承关系,所以输出的结果是false
System.out.println(person instanceof Teacher);//false
//编译报错,Person和String同为Object的子类,同级之间不能转换
//System.out.println(person instanceof String);
System.out.println("================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//编译错误,Student和Teacher同为Person的子类,同级,同级之间不能相互转换
//System.out.println(student instanceof Teacher);
//String是Object的子类,与Student没有继承关系
//.out.println(student instanceof String);
}
}
public class Application2 {
public static void main(String[] args) {
//类型之间的转换: 父类 子类
//高 低
Person person = new Student();
//需要将person这个对象转换为Student类型,我们就可以使用Student类型的方法了
Student person1 = (Student) person;
person1.go();
((Student) person).go();
//子类转换为父类,可能会丢失自己本来的一些方法
Student student = new Student();
student.go();
Person person2 = student;
}
}
/*
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型
3.把父类转换为子类,向下转型:强制转换
4.方便方法的调用,减少重复的代码,是代码变得简洁
抽象:封装、继承、多态 抽象类:接口······
*/
java的动态绑定机制
-
当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
package dynamic; public class Test { public static void main(String[] args) { A a = new B();//向上转型 System.out.println(a.sum());//当调用sum()方法时,先找运行类型B类中的sum方法,方法中调用属性遵循就近原则 System.out.println(a.sum1());//当调用sum1()方法时,先找运行类型B 中的sum1()方法,如果没找到, //去父类中找,找到了就调用父类中的,但是sum1()方法中调用了getI()方法,所以还是遵循调用原则,先找运行类型B 中的 //实现了动态绑定 B a1 = (B) a;//向下转型 System.out.println(a1.i); } } class A { public int i = 10; public int sum(){ return i+20; } public int getI(){ return i; } public int sum1(){ return getI()+10; } } class B extends A{ public int i = 20; public int sum(){ return i+20; } public int getI(){ return i; } public int sum1(){ return getI()+10; } }
-
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
import poly.polyarr.Person;
public class Test1 {
public static void main(String[] args) {
Person[] person = new Person[5];
person[0] = new Person("jack",22);
person[1] = new Student("小明",15,60.6);
person[2] = new Student("小李",15,99.9);
person[3] = new Teacher("老李",35,50000);
person[4] = new Student("盛浩",28,90000);
for (int i = 0; i < person.length; i++) {
//Person[i]编译类型时Person,运行类型时根据实际情况由JVM来判断
System.out.println(person[i].say());//动态绑定机制
if ( person[i] instanceof Student) {//判断person[i]的运行类型是不是Student
Student student = (Student)person[i];//向下转型
//也可以用 ((Student)person[i]).say();
student.study();
} else if (person[i] instanceof Teacher) {//判断person[i]的运行类型是不是Teacher
Teacher teacher = (Teacher) person[i];//向下转型
teacher.teach();
}else if (person[i] instanceof Person) {
}else {
System.out.println("你的代码有误");
}
}
}
}
package poly.polyarr;
//创建一个Person对象,两个Student对象和两个Teacher对象,统一放在数组中,并调用say方法
public class Person {//父类
private String name;//姓名
private int age;//年龄
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;
}
public String say(){
return "姓名:"+name+" 年龄:"+age;
}
}
class Teacher extends Person{//子类
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String say() {
return super.say()+" 工资:"+salary;
}
public void teach(){
System.out.println("教学生");
}
}
class Student extends Person{
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
//重写父类的say方法
@Override
public String say() {
return super.say()+" 成绩:"+score;
}
public void study(){
System.out.println("学会儿");
}
}
- 方法定义的形参类型位父类类型,实参类型允许为子类类型
package poly.polyparameter;
import poly.Master;
//测试类中添加一个方法showEmpAnnual(Employee e),实现获取任何员工对象的年工资
//并在main方法中调用该方法
//测试类中增加一个方法testWork,如果时普通员工,则调用work方法,如果是经理,则调用manage方法
public class PloyParameter {//父类
public static void main(String[] args) {
PloyParameter ployParameter = new PloyParameter();//创建对象方便引用方法
// Manager li = new Manager("li",10000,2000);//创建经理对象
// Ordinary liu = new Ordinary("liu", 5000);//创建普通员工对象
// ployParameter.testWork(liu);
// ployParameter.showEmpAnnual(liu);
// ployParameter.testWork(li);
// ployParameter.showEmpAnnual(li);
Employee[] e = new Employee[2];//用多态数组的方式表示
e[0] = new Manager("威思顿", 10000, 1500);
e[1] = new Ordinary("赞稼", 5000);
for (int i = 0; i < e.length; i++) {
System.out.println(e[i]);
ployParameter.showEmpAnnual(e[i]);
ployParameter.testWork(e[i]);
}
}
public void showEmpAnnual(Employee e) {//查看年薪
System.out.println(e.getAnnual());
}
public void testWork (Employee e){//用来判定运行类型时那个子类,以此来决定调用那个方法
if (e instanceof Manager) {//条件判断其运行类型是不是Manager
((Manager) e).manage();
} else {
((Ordinary) e).work();
}
}
}
package poly.polyparameter;
//包含姓名和月工资[private]。以及计算年工资getAnnual的方法
//普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法
//普通员工多了work方法,普通员工和经理类要求分别重写getAnnual方法
public class Employee {
private String name;//名字
private double salary;//薪水
public Employee(){}
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getAnnual(){
return salary*12;
}
}
package poly.polyparameter;
//普通员工多了work方法
public class Ordinary extends Employee{//普通员工类,子类
public Ordinary(String name, double salary) {
super(name, salary);
}
public void work(){
System.out.println("员工"+getName()+"工作了");
}
@Override
public double getAnnual() {//重写父类的方法
return super.getAnnual();
}
}
package poly.polyparameter;
//经理类多了奖金bonus属性和管理manage方法
public class Manager extends Employee {//经理类,子类
private double bonus;
public Manager(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public void manage(){
System.out.println("经理"+getName()+"进行了管理");
}
public double getAnnual(){
return (getSalary()+bonus)*12;
}
}
## 抽象类和接口
## 接口
- 普通类:只能具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范 自己无法写方法 专业的约束!约束和实现分离:面向接口编程
- 接口就是规范,定义的是一组会泽,体现在现实世界中,“如果你是········则必须能····”的思想
- **接口的本质是契约**,就像我们的法律一样,制定好了大家都要遵守
- oo的精髓,是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式以都只针对具备了抽象能力的语言,就是因为设计模式所研究的,实际上就是如何合理的去抽象
- 只有一个方法的接口叫做函数时接口,可以使用lambda表达式简化
- 抽象类的关键字是class,声明类的关键字是interface
```java
//interface 定义接口的关键字
public interface UserService {
//接口中的所有定义的方法都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//抽象类:extends
//类可以通过implements实现接口
public class UserServiceImp1 implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
public interface TimeService {
void timer();
}
作用:
1.约束
2.定义一些方法,让不同的人实现
3.public abstract 接口中的所有定义的方法都是抽象的
4.public static final 在接口中定义常量
5.接口不能被实例化~ ,接口中没有构造方法
6.接口中可以通过implements实现多个接口
7.在类中必须重写接口中的方法
内部类及oop实战
内部类
- 内部了哦就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B 类相对A 类来说就成为内部类,而A类相对B类来说就是外部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//内部类可以获得外部类的私有属性
public void getId(){
System.out.println(id);
}
}
//局部内部类
public void method(){
class inin{
public void ininin(){
}
}
}
}
public class Test {
public static void main(String[] args) {
//匿名内部类:没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
}
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}