Java 的核心思想就是 OOP
一、初识面向对象
1.面向过程 & 面向对象
-
面向过程思想(线性思维)
- 步骤清晰简单,第一步做什么,第二步做什么……
- 面向过程适合处理一些较为简单的问题
-
面向对象思想:抽象
- 物以类聚, 分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考,最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
-
属性 + 方法就是一个类
2.什么是面向对象
- 面向对象编程(Object Oriented Programming,OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据。(类是用来组织代码的,每一个具体的对象封装每一个具体的数据)
- 抽象(理解:抽像(把像的那一部分抽取出来))
- 三大特性:
- 封装:把数据包装起来
- 继承:父类和子类之间有一个继承关系,子类就拥有父类的所有东西
- 多态:同一个事物会有多种形态(同样是学习,学到的东西不一样)
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
- (先有很多人,然后把人提取出共同特点,就是抽象,抽象出来为某一类,比如老师和学生,先有具体的一个一个人这个对象,然后才去抽象出来一个一个类)
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
- (要先把东西分好类,然后再去实现)
二、方法回顾和加深
1.方法的定义
- 修饰符
- 返回类型
-
break 和 return 的区别
- break :①跳出 switch ;②结束循环
- ( continue :结束一次循环)
- return :方法结束,返回一个结果,返回值必须和返回值类型相同
- 方法名:注意规范(首字母小写和驼峰命名原则),见名知意
- 参数列表:(参数类型 参数名),一个方法可以有多个参数,可以通过
...
定义可变长参数 - 异常抛出:ArrayIndexOutOfBoundsException :数组下标越界异常!
//类
public class DefinitionOfMethod {
//main()方法:用来启动当前这个程序的,一个程序里面只有一个 main() 方法
public static void main(String[] args) {
}
/*
方法的定义:
修饰符 返回值类型 方法名(参数类型 形式参数){
//方法体
return 返回值;
}
*/
// return :结束方法,返回一个结果
public String sayHello(){
return "hello";
}
//如果返回值类型是 void ,返回值可以默认不写,如果要写的话 return; 就好了
public void hello(){
return; //返回空值
}
//比较大小
public int max(int a, int b){
return a > b ? a : b;
}
}
2.方法的调用(递归)
-
静态方法
-
非静态方法
public class MethodCall_StaticMethod { public static void main(String[] args) { //静态方法 static :直接通过 类名.方法名() 调用方法 Student.say(); //学生说话 //非静态方法:通过 new 实例化这个类 //对象类型 对象名 = 对象值; Student student = new Student(); student.read(); //学生读书 new Student().read(); //学生读书 } } //学生类 class Student{ //静态方法 static :直接通过 类名.方法名() 调用方法 public static void say(){ System.out.println("学生说话"); } //非静态方法:通过 new 实例化这个类 public void read(){ System.out.println("学生读书"); } }
public class MethodCall_StaticMethod { //两个静态方法是可以直接调用的 //两个非静态方法是可以直接调用的 //静态方法无法直接调用非静态方法 //非静态方法可以直接调用静态方法 //和类一起加载的,类存在的时候就已经存在了 public static void a(){ b(); // c(); //已经存在的调用不存在的东西会报错 } public static void b(){ } //对象创建(类实例化)之后才存在 public void c(){ a(); d(); } public void d(){ } }
-
形参和实参
public class MethodCall_FormalAndRealParameters { public static void main(String[] args) { //实际参数:真实的参数,实际参数和形式参数的类型要对应 int add = MethodCall_FormalAndRealParameters.add(1, 2); System.out.println(add); } //形式参数:占位符,真实不存在,形式参数可以随便写,但是,真实传递进去的类型要一一对应 public static int add(int a, int b){ return a + b; } }
-
值传递和引用传递: Java 里面都是值传递
//值传递 public class MethodCall_ValuePassing { public static void main(String[] args) { int i = 1; System.out.println(i); //1 MethodCall_ValuePassing.change(i); System.out.println(i); //1 } //返回值为空 public static void change(int i){ i = 10; } }
//引用传递:传递一个对象,本质还是值传递 public class MethodCall_ReferencePassing { public static void main(String[] args) { Person person = new Person(); System.out.println(person); System.out.println(person.name); //null BMethodCall_ReferencePassing.change(person); System.out.println(person.name); //张三 } public static void change(Person person){ // person 是一个对象,指向 --> Person person = new Person(); 这是一个具体的人,可以改变属性 person.name = "张三"; } } //定义了一个 Person 类,有一个 name属性 class Person{ String name; //null }
-
this 关键字
三、对象的创建分析
1.类与对象的关系
-
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
- 动物(猫、狗、猪)、植物(树、花、草)、手机、电脑……
- Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
-
对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
- 能够体现出特点,展现出功能的是具体的实例,而不是抽象的概念。
-
我们可以将这些思想转换为代码实现!
2.创建与初始化对象
- 使用 new 关键字创建对象
- 使用 new 关键字创建对象的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
public class CreateObject {
public static void main(String[] args) {
//类是抽象的,需要实例化,变成一个对象:通过 new 关键字实例化
//类实例化之后会返回一个自己的对象:类是抽象的,对象是具体的实例
// zhangsan 对象就是 Student 类的具体实例
Student zhangsan = new Student();
Student lisi = new Student();
zhangsan.name = "张三";
zhangsan.age = 23;
System.out.println(zhangsan.name); //张三
System.out.println(zhangsan.age); //23
System.out.println(lisi.name); //null
System.out.println(lisi.age); //0
}
}
//学生类:一个抽象的模板
class Student {
//一个类里只可能存在这两个东西:属性和方法
//属性:字段
String name; //默认为 null
int age; //默认为 0
//方法:行为
public void study(){
System.out.println(this.name + "学习");
}
}
3.构造器
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写 void
- 构造器必须掌握
- IDEA快捷键: alt + ins 快速生成构造器
public class Constructor {
public static void main(String[] args) {
//通过 new 关键字实例化一个对象,调用构造器
//调用无参构造器
Person zhangsan = new Person();
System.out.println(zhangsan.name); //张三
//调用有参构造器
Person lisi = new Person("李四");
System.out.println(lisi.name); //李四
}
}
class Person{
String name;
//一个类即使什么都不写,也会存在一个方法,默认的无参构造器
//显式的定义构造器:名字与类名相同,并且没有返回值的方法
//构造器的作用:
//1. 使用 new 关键字,必须要有构造器:本质是在调用构造器
//2. 构造器用来初始化值:
//无参构造器:定义了有参构造器,默认把无参构造器空着就行,里面什么都不用写
Person(){
//初始化一些信息
this.name = "张三";
}
//有参构造器:一旦定义了有参构造器,无参构造器就必须显式定义,否则无参构造器就无效
Person(String name){
this.name = name;
}
}
-
总结:
-
构造器:
-
特点:
- 方法名和类名相同
- 没有返回值
-
作用:
- new 本质在调用构造器
- 初始化对象的值
-
注意点:
- 定义了有参构造器之后,如果想使用无参构造器,必须要显式的定义一个无参构造器
-
-
4.创建对象内存分析
public class CreateObjectMemoryAnalysis {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}
//宠物类
class Pet{
String name;
int age;
//无参构造器
public void shout(){
System.out.println("宠物会叫");
}
}
- 为什么同时 new 的都是 Pet 但是会产生不一样的对象?
- 因为是不同的区域,而它的地址不同,引用变量名不同
5.总结
- 类与对象
- 类是一个抽象的模板,对象是一个具体的实例
- 方法
- 定义、调用
- 避免方法的死循环
- 方法的定义格式要知道
- 对象的引用(引用就是指向对象的一个地址,用的是栈里面的一个引用,真实操作的是堆)
- 引用类型(除了基本类型都是引用类型) < -- > 基本类型(8个)
- 对象是通过引用来操作的:栈 --> 堆(真实对象在堆里面,地址)
- 属性:字段、 Field 、成员变量
- 默认初始化
- 数字:0 0.0
- char :u0000
- boolean : false
- 引用类型: null
- 定义
- 修饰符 属性类型 属性名 = 值;
- 默认初始化
- 对象的创建和使用
- 必须使用 new 关键字创建对象,必须有构造器
Person zhangsan = new Person();
- 调用对象的属性
zhangsan.name
- 调用对象的方法
zhangsan.study()
- 必须使用 new 关键字创建对象,必须有构造器
- 类中只有两个东西:
- 静态的属性:属性
- 动态的行为:方法
四、面向对象三大特性(封装、继承、多态)
1.封装(外部不可以直接访问,通过内部方法访问调了一个接口)
-
该露的露,该藏的藏:把该暴露给用户的一些东西暴露出来,但大部分程序的一些细节都应该藏起来
- 我们程序设计要追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
-
属性私有,getXxx() / setXxx()
-
IDEA快捷键: alt + ins 快速生成 get / set 方法
-
封装的意义:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 提高系统的可维护性
public class Encapsulation {
public static void main(String[] args) {
Student zhangsan = new Student();
zhangsan.setName("张三");
System.out.println(zhangsan.getName()); //张三
zhangsan.setAge(120); //不合法
System.out.println(zhangsan.getAge());
}
}
//学生类 private :私有,封装的核心
class Student {
//封装大多数时候是对于属性来的,对于方法用的比较少
//属性私有,属性私有的时候,一般使用 private
private String name; //名字
private int id; //学号
private char sex; //性别
private int age; //年龄
//提供一些可以操作这个属性的方法( public 的 get / set 方法)
// get :获得这个数据
public String getName() {
return this.name;
}
// set :给这个数据设置值
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
//由于封装过了,可以做一些安全性检查
public void setAge(int age) {
if (0< age && age < 150) {
this.age = age;
} else { //不合法
this.age = 18;
}
}
}
- 封装是对一个对象的封装,对一个类的封装
2.继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extends 的意思是“扩展”。子类是父类的扩展。
- Java 中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字 extends 来表示。
- 子类和父类之间,从意义上讲应该具有“ is a ”的关系。
- 子类可以继承父类的所有方法
- object 类:在 Java 中,所有的类都默认直接 / 间接继承 Object 类
public class Inheritance_Inheritance {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.say(); //说话
System.out.println(teacher.getMoney()); //1000000000
}
}
//人 :基类 / 父类
//在 Java 中,所有的类都默认直接 / 间接继承 Object 类
class Person /*extends Object*/ {
//修饰符
//public:公共的
//protected:受保护的
//default:默认的,可以不写
//private:私有的,一般属性才是私有的
private int money = 10_0000_0000;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void say(){
System.out.println("说话");
}
}
//老师 is 人 :派生类 / 子类
//子类继承了父类,就会拥有父类的全部方法
class Teacher extends Person{}
//医生 is 人 :派生类 / 子类
class Doctor extends Person{}
-
super 注意点:
- super 调用了父类的无参构造器,必须要在子类构造器的第一行方法重写
- super 必须只能出现在子类的方法或构造方法中,在自己的类调用 super ,调用的是 Object
- super 和 this 不能同时调用构造方法,同时调用的话必须保证在第一行,两个肯定有一个报错
-
super 和 this 的区别:
- 代表的对象不同:
- this :代表本身调用者这个对象
- super :代表父类对象的引用
- 前提不一致:
- this :没有继承也可以使用
- super :只能在继承条件下才可以使用
- 构造方法有区别:
- this() :调用的本类的构造器
- super() :调用的父类的构造器
public class Inheritance_Super {
public static void main(String[] args) {
Dog dog = new Dog(); //Pet无参构造器 Dog无参构造器
dog.testName("吉利");
dog.testPrint();
}
}
//宠物
class Pet {
//假如父类里面没有无参构造器,直接写一个有参构造器,子类不仅调用不了父类的无参构造器,而且写不了无参构造器,
//因为父类无法写,子类也没发写,代码在去检查的时候就通过不了
public Pet() {
System.out.println("Pet无参构造器");
}
protected String name = "姓名";
public void print(){
System.out.println("Pet");
}
//私有的东西无法被继承
private void selfish(){}
}
//狗
class Dog extends Pet{
public Dog() {
super(); //隐藏代码,调用了父类的无参构造器,必须要在子类构造器的第一行,不写的话,默认调用父类的无参构造器
// this(); //必须要在构造器的第一行,调用构造器的话,要么调用父类的,要么调用子类的,只能在代码的第一行,不能写到其他地方
System.out.println("Dog无参构造器");
}
public Dog(String name) {
this.name = name;
}
private String name = "旺财";
@Override
public void print(){
System.out.println("Dog");
}
public void testName(String name){
System.out.println(name); //吉利,实参name
System.out.println(this.name); //旺财,子类的name
System.out.println(super.name); //姓名,父类的name
}
public void testPrint(){
print(); //Dog,子类的print()
this.print(); //Dog,子类的print()
super.print(); //Pet,父类的print()
}
}
-
方法重写(需要有继承关系,子类重写父类的方法,属性是没有重写的) ==> 多态
- 方法名必须相同
- 参数列表必须相同
- 修饰符:子类范围可以扩大( public > protected > default > private )
- 抛出的异常的范围:可以被缩小,但不能扩大( ClassNotFoundException < Exception )
-
重写,就是子类的方法(方法名、方法参数)和父类必须要一致,方法体不同
-
为什么需要重写?
- 父类的功能,子类不一定需要,或者不一定满足(父类的东西太多了,子类只需要一点点,或者,父类的东西太少了,子类不满足,需要把一些新的方法进行重写)
- 因为有些东西不能走老路,要自己学会摸索、探究,这就是重写带来的价值
public class Inheritance_Override {
public static void main(String[] args) {
//静态方法和非静态方法区别很大
//静态方法:方法的调用只和左边定义的数据类型有关,静态方法在类一加载就出来了
//非静态方法:重写
//重写跟静态方法无关,只跟非静态方法有关
/*
b 是 A new 出来的对象,因此调用了 A 的方法
有 static 时, b 调用了 B 类的方法,因为 b 是用 B 类定义的
没有 static 时, b 调用了对象的方法,因为 b 是用 A 类 new 出来的对象
静态方法是类的方法,非静态方法是对象的方法
*/
A a = new A();
a.printStatic(); //A==>printStatic()
a.print(); //A==>printStatic()
//父类的引用指向子类的对象
B b = new A(); //向上转型,类型转换
b.printStatic(); //B==>printStatic()
b.print(); //A==>printStatic(),子类重写了父类的方法
}
}
//重写都是方法的重写,和属性无关
class B{
public static void printStatic(){
System.out.println("B==>printStatic()");
}
public void print(){
System.out.println("B==>print()");
}
}
//继承
class A extends B{
public static void printStatic(){
System.out.println("A==>printStatic()");
}
//重写
@Override //注解:有功能的注释
public void print(){
System.out.println("A==>print()");
}
}
- IDEA快捷键: 重写
- IDEA快捷键: F4 ( ctrl + h )打开继承树
3.多态(编译,看左边;运行,看右边)
-
可以实现动态编译:类型的最终状态只有在执行过程中才可以决定,使可扩展性变得更强
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类 / 有关系的类)
-
注意:
- 多态是方法的多态,属性没有多态性
- 父类和子类要有联系(如果类型不匹配,会报类型转换异常 ClassCastException)
- 多态存在的必要条件:
- 要有继承关系
- 方法需要重写(方法如果不重写,调用的都是各自的方法,就没有任何区别了)
- 有些方法不能被重写
- static 静态方法:属于类的,不属于实例
- final 常量方法:被 final 修饰的就无法修改了,在常量池里面
- private 私有方法:父类私有的
- 有些方法不能被重写
- 父类引用指向子类对象
Father father = new Son();
public class Polymorphism_Polymorphism {
public static void main(String[] args) {
//一个对象的实际类型是确定的, new 了什么,就是什么
// new Animal();
// new Cat();
//可以指向的引用类型就不确定了
//子类能调用的方法都是自己的或者继承父类的
Cat cat = new Cat();
//父类型,虽然可以指向子类,但是不能调用子类独有的方法
Animal animal = new Cat(); //父类的引用指向子类的对象
Object object = new Cat(); //父类的引用指向子类的对象
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
//如果子父类都有的情况下,只要子类没有重写父类,那么就调用父类的,如果子类重写了父类,就调用子类的
//子类重写了父类的方法,执行子类的方法
animal.print(); //Cat==>print()
cat.print(); //Cat==>print()
((Cat) animal).cat(); //Cat==>cat()
}
}
//动物
class Animal{
public void print(){
System.out.println("Animal==>print()");
}
}
//猫
class Cat extends Animal{
@Override
public void print() {
System.out.println("Cat==>print()");
}
public void cat() {
System.out.println("Cat==>cat()");
}
}
- instanceof 引用类型转换,判断一个对象是什么类型,可以判断两个对象之间是否存在父子关系
- 编译,看左边;运行,看右边。
public class Polymorphism_Instanceof {
public static void main(String[] args) {
//总结:编译,看左边;运行,看右边。
//Object > String
//Object > Plants > Flower
//Object > Plants > Tree
Object object = new Tree();
//一般可以先通过 instanceof 判断类型是否相似,然后再进行强制转换
System.out.println(object instanceof Tree); //true
System.out.println(object instanceof Plants); //true
System.out.println(object instanceof Object); //true
System.out.println(object instanceof Flower); //false
System.out.println(object instanceof String); //false
System.out.println();
//Plants > Flower
//Plants > Tree
Plants plants = new Tree();
System.out.println(plants instanceof Tree); //true
System.out.println(plants instanceof Plants); //true
System.out.println(plants instanceof Object); //true
System.out.println(plants instanceof Flower); //false
// System.out.println(plants instanceof String); //编译报错
System.out.println();
//Plants > Tree
Tree tree = new Tree();
System.out.println(tree instanceof Tree); //true
System.out.println(tree instanceof Plants); //true
System.out.println(tree instanceof Object); //true
// System.out.println(tree instanceof Flower); //编译报错
// System.out.println(tree instanceof String); //编译报错
System.out.println();
//类型之间的转换:基本类型转换
//高 低
Plants plants1 = new Tree();
//强制类型转换
//将高类型对象转换为低类型,就可以使用低类型的方法了
Tree tree1 = (Tree) plants1;
tree1.printTree(); //Tree==>printTree()
((Tree) plants1).printTree(); //Tree==>printTree()
//自动类型转换
//子类转换为父类,可能会丢失自己本来的一些方法
Tree tree2 = new Tree();
Plants plants2 = tree2;
tree2.printPlants(); //Plants==>printPlants()
}
}
//植物
class Plants{
public void printPlants(){
System.out.println("Plants==>printPlants()");
}
}
//树
class Tree extends Plants{
public void printTree(){
System.out.println("Tree==>printTree()");
}
}
//花
class Flower extends Plants{}
总结:
- 父类引用指向子类对象
- 把子类转换为父类,向上转型(自动类型转换);把父类转换为子类,向下转型(强制类型转换),会丢失一些方法
- 方便方法的调用,减少重复的代码
五、static、final
1.static
public class Static_Static {
private static int age; //静态变量,对于类而言,在内存中只有一个,能被类中的所有实例共享
private int score; //非静态变量
//静态方法:可以调用静态方法里面的所有东西,不能调用普通方法的
public static void printStatic(){
System.out.println("printStatic()");
}
//非静态方法:可以调用静态方法里面的所有东西
public void print(){
System.out.println("print()");
}
public static void main(String[] args) {
A_Static_A_Static a_static_a = new A_Static_A_Static();
System.out.println(a_static_a.age);
System.out.println(a_static_a.score);
System.out.println(A_Static_A_Static.age); //静态变量推荐使用 类名.变量 调用
// System.out.println(A_Static_A.score); //非静态变量不能这样使用
System.out.println();
A_Static_A_Static.printStatic();
printStatic();
// print(); //非静态方法不能这样使用
new A_Static_A_Static().print();
}
}
2.静态代码块
//静态导入包,下面可以直接调用
import static java.lang.Math.random;
public class Static_StaticCodeBlock {
static {
//静态代码块:永久只执行一次,加载初始化的数据,方便初始化一些东西,类一加载直接执行,
System.out.println("1. 静态代码块");
}
{
//匿名代码块:赋初始值,不建议这么写,创建对象的时候自动创建,在构造器之前
System.out.println("2. 匿名代码块");
}
public A_Static_B_StaticCodeBlock() {
System.out.println("3. 构造方法");
}
public static void main(String[] args) {
/*
静态代码块
匿名代码块
构造方法
*/
Static_BStaticCodeBlock static_staticCodeBlock = new Static_StaticCodeBlock();
System.out.println();
/*
匿名代码块
构造方法
*/
Static_StaticCodeBlock static_staticCodeBlock1 = new Static_StaticCodeBlock();
// System.out.println(Math.random());
System.out.println(random());
}
}
3.final(常量)
- 通过 final 修饰的类,不能被继承,没有子类
六、抽象类和接口
1.抽象类(abstract,抽象的抽象:约束)
-
abstract 修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
-
抽象类,不能使用 new 关键字来创建对象,它是用来让子类继承的。
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
-
总结:
- 抽象类,不能 new 这个抽象类,只能靠子类实现它,就是一个约束
- 抽象类中可以写普通方法,抽象方法必须在抽象类中
-
思考:
-
抽象类既然不能 new 对象,那么存在构造器吗?
- 抽象类中一定有构造器,便于子类实例化时调用
-
抽象类存在的意义是什么?
- 将共有属性抽象出来,节省代码开发,提高开发效率,提高可扩展性
-
public abstract class Abstract_Abstract {
public static void main(String[] args) {
//1. 抽象类,不能 new 这个抽象类,只能靠子类实现它,就是一个约束
// new Action();
}
}
//abstract:抽象类 extends:单继承,没办法继承多个类(接口可以多继承)
abstract class Action{
//约束:有人帮我们实现
//abstract:抽象方法,只有方法名,没有方法的实现
public abstract void doSomething();
//2. 抽象类中可以写普通方法,抽象方法必须在抽象类中
public void print(){
System.out.println("Action");
}
}
//抽象类的所有方法,都必须要由继承它的子类实现,除非,子类也是抽象类,那就没必要实现了,让子子类实现
class A extends Action{
@Override
public void doSomething() {
}
}
2.接口(面向接口编程)
- 普通类:只有具体的实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范(自己无法写方法,比抽象类还要抽象的抽象,专业的抽象,专业的约束,可以实现约束和实现分离)
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是……则必须能……”的思想。如果你是汽车,则必须能跑。
- 接口的本质是契约,就像法律一样,制定好后大家都遵守。
- OO (面向对象)的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言( C++ 、 Java 、C# 等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
- 声明类的关键字是 class ,声明接口的关键字是 interface
- 总结(接口的作用):
- Java 的接口是一个约束
- 定义一些方法,让不同的人实现
- 接口中的所有定义的方法其实都是抽象的, public abstract 的
- 接口中定义的属性都是静态的常量, public static final 的
- 接口不能被实例化,接口中没有构造方法
- 可以通过 implement 关键字实现多个接口
- 实现类必须要重写接口中的方法
//抽象的思维
public class Abstract_Interface {
public static void main(String[] args) {
}
}
//类里面有方法的实现,接口只有方法的定义,通过 interface 来定义
//用户业务,interface:接口定义的关键字,接口都需要有实现类
interface UserService{
//接口中定义的属性都是静态的常量, public static final 的,一般不这么做
// public static final int AGE = 18;
int AGE = 18;
//接口中的所有定义的方法其实都是抽象的, public abstract 的
// public abstract void run();
void run();
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//时间业务
interface TimeService{
void timer(); //计时
}
//抽象类:extends
//一个类可以通过 implement 关键字实现接口
//实现了接口的类,就需要重写接口中的方法
//Java 虽然是单继承,但是可以利用接口实现多继承
class UserviceImpl implements UserService, TimeService{
@Override
public void run() {
}
@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() {
}
}
七、内部类
- 内部类就是在一个类的内部再定义一个类,比如, A 类中定义一个 B 类,那么 B 类相对 A 类来说就称为内部类,而 A 相对 B 类来说就是外部类了。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
public class InnerClass {
public static void main(String[] args) {
//外部类通过 new 关键字实现
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner =outer.new Inner();
// Outer.Inner inner =new Outer().new Inner();
inner.in(); //Inner-->in()
inner.getId(); //18
//4. 匿名内部类:没有名字初始化类,不用将实例保存到变量中
new Outer().out();
new Uservice() {
@Override
public void run() {
}
};
// Uservice uservice = new Uservice() {
// @Override
// public void run() {
//
// }
// };
}
}
class Outer{
private int id = 18;
public void out(){
System.out.println("Outer-->out()");
}
//1. 成员内部类
public class Inner{
public void in(){
System.out.println("Inner-->in()");
}
//内部类可以直接获得外部类的一些私有属性 / 私有方法
public void getId(){
System.out.println(id);
}
}
//2. 静态内部类
public static class InnerStatic{
public void in(){
System.out.println("Inner-->in()");
}
//静态内部类没办法访问非静态的属性
// public void getId(){
// System.out.println(id);
// }
}
public void method(){
//3. 局部内部类
class Inner{
public void in(){
System.out.println("Inner-->in()");
}
}
}
}
//这个不能是 public ,一个 Java 类中只能有一个 public class ,可以有多个 class
class Inner{}
interface Uservice{
void run();
}