请分析以下对象都有哪些属性和方法?
比如:手机
属性
方法
比如:汽车
我们学习编程的目的就是为了将生活中的事和物用程序语言描述出来
类是一种事物的统称,是对象的模板。类是一种虚拟的概念。看不见、摸不着。
什么是类?举个例子:汽车是怎么创造出来的?
类的抽取
static
暂时不要了;/**
* class >> 类
* 类:是一种事物的统称,是对象的模板。类是一种虚拟的概念。看不见,摸不着。
* 比如:人类、桌子、凳子、汽车、飞机。
* 人会吃饭 == > 人指的是类。
* 对象:万事万物皆对象。对象是这个世界上实实在在存在的个体。你看到的任何一个东西都是一个对象。
* 今天我跟小红取吃饭 == > 我、小红就是人类的实体 == 对象
** 类和对象的关系* 类是模板,是图纸,对象是根据模板(图纸)创建出来的一个实实在在的个体。* 造汽车:需要先准备图纸,宝马先造出一辆,然后开发布会,开始量产
*
* */
创建一个学生类
package com.goshawk.object;
/*** 定义一个学生类-学生的模板* 此时是在定义一个学生具备怎么的属性和功能(方法)** */
public class Student {// 属性:成员变量(局部变量)long id;String name;int age;// 能力/功能/方法:比如 学习、吃饭、睡觉void study(){System.out.println("正在学习...");}void eat(){System.out.println("正在吃饭...");}void sleep(){System.out.println("现在睡觉...");}}
创建一个老师类
package com.goshawk.object;public class Teacher {String name;int age;String schoolName;void teach(){System.out.println("开始上课...");}
}
创建一个业务类
package com.goshawk.object;
/*** 面向对象的第一个案例** */
public class TestObject {public static void main(String[] args){//1> 苍鹰老师开始上课//2> 小明同学开始学习// 创建一个老师的对象 ==> 用Teacher类来床加你一个对象Teacher teacher= new Teacher();// 给老师取名teacher.name = "Goshawk";// 让老师上课teacher.teach();// 使用Student类来创建一个实实在在的学生个体Student student = new Student();student.name = "小明";student.age = 22;student.id = 10001L;student.study();}
}
如何定义类?
/**
属性:通过变量表示,又称实例变量。
语法:数据类型 属性名;
位置:类的内部,方法的外部。方法:通过函数表示,又称为实例方法。语法:
public 返回值类型 方法名(形参){// 方法主体
}
*/public class Dog{String breed; // 品种int age;String sex;String furColor; // 毛色public void eat(){System.out.println("eating");}public void sleep(){System.out.println("sleep");}
}
如何创建对象?
/**
将对象保存在相同类型的dog变量中,dog变量称为对象名或者引用名
*/
public class TestCreatObect{public static void main(String[] args){Dog dog = new Dog(); // 基于Dog类创建对象dog.breed = "萨摩";dog.age = 2;dog.sex = "公";dog.furColor = "白色";// 访问属性:对象名.属性名; --> 取值System.out.println(dog.breed + "\t" + dog.age + "\t" + dog.sex + "\t" + dog.furColor);// 调用方法:对象名.方法名();dog.eat();dog.sleep();}
}
package com.goshawk.chap01;public class Student {String name;int age;String sex;double score;public void sayHi(){System.out.println("大家好,我是"+name+"\t"+"现在"+age+"岁,性别"+sex+",分数:"+score);}
}
package com.goshawk.chap01;public class TestStudent {public static void main(String[] args) {Student s1 = new Student();s1.name = "小明";s1.age = 18;s1.sex = "男";s1.score = 98;s1.sayHi();Student s2 = new Student();s2.name = "小丽";s2.age = 18;s2.sex = "女";s2.score = 99;s2.sayHi();}
}
public class TestConstructors{public static void main(String[] args){// new Student(); 触发对象创建Student s = new Student();}
}class Student{String name;int age;String sex;double score;public Student(){System.out.println("Student() Executed");}
}
Student s = new Student();
s.name = "tom";
s.age = 20;
s.sex = "male";
s.score = 98.5;# 变量s(引用)中保存对象的地址,通过变量中的地址访问对象的属性和方法。
结合 2.4
面向对象的第一个案例
Student stu = new Student();
:
package com.goshawk.object;
/*** 对象的使用* 对象的使用就是在使用对象中的属性和方法* 此时对象的使用关键是如何通过对象名来找到属性和方法?* 格式:* `对象.属性` 和 `对象.方法()`的形式来使用对象*/
public class TestObject2 {public static void main(String[] args){Student stu = new Student();// 使用对象属性stu.id = 1001L;// 通过 . 的方式,找到对象这块空间里面的name空间stu.name = "xiaoming";System.out.println("学生:"+stu.name+"id:"+stu.id);// 调用对象的方法stu.study();stu.eat();stu.sleep();}
}
基于面向对象的程序设计是怎么做的?
面向对象的重点是什么?
重点不是使用对象;使用对象相当于是设计阶段已经结束了;
面向对象的重点是:设计类!
在设计好了类以后如何使用类?
如何设计类呢?
设计类就是要设计类的内容。类的内容包括五个部分。这五个部分不是必须都得全部出现。
什么是类的属性,其实就是类的成员变量;
思考:之前学习局部变量时,要求必须先赋值再使用,否则编译错误。对于实例变量而言,未赋值并不会编译错误,能否直接访问。
从声明的位置来划分:成员变量和局部变量
成员变量和局部变量的区别
局部变量 | 实例变量 | |
---|---|---|
定义位置 | 方法或者方法内的结构当中 | 类的内部,方法的外部 |
默认值 | 无默认值 | 字面值(与数组相同) |
使用范围 | 从定义行到包含其结构结束 | 本类有效 |
命名冲突 | 不允许重名 | 可与局部变量重名,局部变量优先 |
举个例子:
package com.goshawk.object;
/*** 基于面向对象的程序设计是怎么做的?* */// 一个文件可以有两个类,但是只有一个类是被public修饰
public class DesignClass {public static void main(String[] args) {Implement implement = new Implement();implement.getName();}}class Implement{// name属性:成员变量,在创建对象时,成员变量的空间就被开辟了String name;public void show(){// 局部变量:当调用该方法时,该局部变量才会被创建(堆空间)String address = "abc";}public void getName(){System.out.println(name);// System.out.println(address);}
}
就是一段代码的整合;
举个例子:
package com.goshawk.object;public class TestDemo {public static void main(String[] args) {Student student = new Student();student.eat();student.sleep();}}
下图是分析上述代码的内存变化:
方法在调用时,会创建一个方法的栈帧,存入到栈中,随着方法执行完毕,该栈帧会出栈。于是方法中的局部变量也会被销毁。
将一些描述一个功能的相关代码整合在一起。
对象的实例方法包含两部分:
有些情况下,对象的同一种行为可能存在多种实现过程。
例如:人对象的吃行为,吃饭和吃药的过程就存在差异。
到底采用哪种实现形式,需要取决于调用者给定的参数。
public class Person{public void eat(食物 a){// 食物放入口中// 咀嚼// 咽下}public void eat(药物 b){// 药物放入口中// 喝水// 咽下}public void eat(口香糖 c){// 口香糖放入口中// 咀嚼// 吐出}
}
重载(Overload):一个类中定义多个相同名称的方法
要求:
调用带有重载的方法时,需要根据传入的实参去找到与之匹配的方法。
好处:屏蔽使用差异,灵活、方便。
package com.goshawk.chap01;public class Operation {public void show(){System.out.println("无参数方法");}public void show(int num){System.out.println("一个int类型参数"+num);}public void show(String name){System.out.println("一个String类型参数"+name);}public void show(int num, String name){System.out.println("两个参数 int、String:"+num+"\t"+name);}public void show(String name, int num){System.out.println("两个参数 String、int:"+name+"\t"+num);}
}
package com.goshawk.chap01;public class TestOperation {public static void main(String[] args) {Operation operation = new Operation();operation.show();operation.show(99);operation.show("小李");operation.show(88, "小赵");operation.show("小钱", 77);}
}
思考:以下方法是不是重载?
public void m(int a){}
public void m(int v){}
两个方法的方法名称和参数列表都相同,只有参数名称不一样,编译报错。
注意:只是参数名称不同,并不能构成方法的重载。
什么是构造方法:类中用于创建对象的特殊方法,名称与类名相同,没有返回值类型,不可通过句点调用。
举个例子:
package com.goshawk.object;public class Cat {String name;int age;public Cat(){// System.out.println("cat的构造方法");name = "Hellokity";age = 2;}
}
package com.goshawk.object;
/*** 类的第三个成员:构造器(构造方法)* ne Student(); 是使用new关键字+构造方法()* 什么是构造方法:就是用来构造对象的,创造对象的。* 一般情况下,可以通过构造方法给对象的属性赋值* 构造方法的作用:* 1> 创建对象* 2> 给对象的属性赋值* */
public class Constructor {public static void main(String[] args) {// 声明一个对象: Student student// new 一个对象:new Student(); Student():调用方法 - 方法名();// Student student = new Student();// 调用Cat()这个构造方法Cat cat = new Cat();System.out.println(cat.name);System.out.println(cat.age);}
}
上述代码的内存变化分析
package com.goshawk.object;
/*** 构造器的格式与构造器的重载* 1、构造器的声明格式* public(或者其它权限修饰符) 类名(参数列表){具体要执行的内容}* 注意:方法名必须是类名,没有返回值(比如:void,如果加上void就会编程一个普通方法)* * */
public class TestObject3 {}class Dog{String name;int age;// 构造方法的名称要与类名一致// public(或者其它权限修饰符) 类名(参数列表){具体要执行的内容}public Dog(){}
}
package com.goshawk.object;
/**** 构造器的重载* 构造器的重载与方法的重载是一个意思:* 在一个类中,有多个构造器,但是多个构造器的参数列表是不同的* 参数列表的不同指的是:参数的个数、类型、顺序不同。* * */
public class TestObject3 {public static void main(String[] args) {Dog d1 = new Dog();System.out.println(d1.name);Dog d2 = new Dog("lucky");System.out.println(d2.name);Dog d3 = new Dog("lili", 1);System.out.println(d3.name);}}class Dog{String name;int age;public Dog(){name = "xiaoqiang";}public Dog(String n){name = n;}public Dog(int a){age = a;}public Dog(String n, int a){name = n;age = a;}
}
package com.goshawk.chap01_2;public class StudentStructure {String name;int age;String sex;double score;public StudentStructure(){System.out.println("StudentStructure() Executed");System.out.println("空参构造器");}public StudentStructure(String n){System.out.println("StudentStructure(String n) Executed");name = n;System.out.println("一个参数,name:"+name);}public StudentStructure(String n, int a){System.out.println("StudentStructure(String n, int ) Executed");name = n;age = a;System.out.println("两个参数,name、age:"+name +"\t" + age);}public StudentStructure(String n, int a, String s){System.out.println("StudentStructure(String n, int a, String s) Executed");name = n;age = a;sex = s;System.out.println("三个参数,name、age、sex:"+name +"\t" + age +"\t" + sex);}public StudentStructure(String n, int a, String s, double sc){System.out.println("StudentStructure(String n, int a, String s, double sc) Executed");name = n;age = a;sex = s;score = sc;System.out.println("四个参数,name、age、sex、score:"+name +"\t" + age +"\t" + sex +"\t" + score);}public void sayHi(){System.out.println("大家好,我是"+name+"\t"+"现在"+age+"岁,性别:"+sex+",分数:"+score);}
}
package com.goshawk.chap01_2;public class TestStudentStructure {public static void main(String[] args) {// 创建对象时,根据传入参数,匹配对应的构造方法。StudentStructure s1 = new StudentStructure();StudentStructure s2 = new StudentStructure("tom");s2.sayHi();StudentStructure s3 = new StudentStructure("jack", 21);s3.sayHi();StudentStructure s4 = new StudentStructure("smith", 22, "male");s4.sayHi();StudentStructure s5 = new StudentStructure("tony", 23, "male", 97.5);s5.sayHi();}
}
class Student{String name;int age;String sex;double score;public Student(String n,int a,String s,double sc){}
}
public class TestStudent{public static void main(String[] args){// 编译错误:无参构造方法未定义Student s1 = new Student();}
}
package com.goshawk.object;public class Fox {String name;int age;public Fox(){System.out.println("hello fox...");}public Fox(String n){name = n;}
}
package com.goshawk.object;/*** 创建类时不声明构造器和只声明了带参的构造器的区别:** 创建类时不声明构造器并不意味着没有构造器,而是jvm会给一个默认的空参的构造器。* 创建类时如果声明了任意一个构造器,那么jvm就不会给默认的空参的构造器。* 因此,建议当在类中声明带参的构造器的同时,要声明一个空参的构造器* */
public class TestObject4 {public static void main(String[] args) {Fox fox = new Fox();System.out.println(fox.name);Fox fox1 = new Fox("abc");System.out.println(fox1.name);}
}
this.
访问实例成员;通过this()/this(xxx)
访问本类中的其他构造方法。public class TestThisKeyword{/**类是模板,可服务于此类的所有对象;this是类中的默认引用,代表当前实例;当类服务于某个对象时,this则指向这个对象。*/public static void main(String[] args){// 0x0000A001Student s1 = new Student();s1.sayHi();// 0x0000B002Student s2 = new Student();s2.sayHi();}
}class Student{String name;int age;String sex;double score;public void sayHi(){/**当创建s1对象时,this指向0x0000A001,访问的name属性即是0x0000A001地址中的name空间;当创建s2对象时,this指向0x0000A001,访问的name属性即是0x0000B002地址中的name空间;*/System.out.println("this.name");}
}
如果成员变量与局部变量名相同,由于局部变量没那的优先级高,那么怎么访问实例变量?
this
以下是成员变量与局部变量名不同(即不冲突)用法:
package com.goshawk.chap01_2;public class StudentStructure {String name;int age;String sex;double score;public StudentStructure(){System.out.println("StudentStructure() Executed");System.out.println("空参构造器");}public StudentStructure(String n){System.out.println("StudentStructure(String n) Executed");name = n;System.out.println("一个参数,name:"+name);}public StudentStructure(String n, int a){System.out.println("StudentStructure(String n, int ) Executed");name = n;age = a;System.out.println("两个参数,name、age:"+name +"\t" + age);}public void sayHi(){System.out.println("大家好,我是"+name+"\t"+"现在"+age+"岁,性别:"+sex+",分数:"+score);}
}
以下是成员变量与局部变量名相同(即冲突),使用this
访问用法:
package com.goshawk.chap01_2;public class StudentStructure {String name;int age;String sex;double score;public StudentStructure(){System.out.println("StudentStructure() Executed");System.out.println("空参构造器");}public StudentStructure(String name){System.out.println("StudentStructure(String name) Executed");this.name = name;System.out.println("一个参数,name:"+this.name);}public StudentStructure(String name, int age){System.out.println("StudentStructure(String name, int age) Executed");this.name = name;this.age = age;System.out.println("两个参数,name、age:"+this.name +"\t" + this.age);}public void sayHi(){System.out.println("大家好,我是"+this.name+"\t"+"现在"+this.age+"岁,性别:"+this.sex+",分数:"+this.score);}
}
package com.goshawk.object;/*** this关键字(类中出现)* 1、this修饰属性* 比如: this.name = name;* 表示当前对象的属性,this.name表示当前对象的name属性* */
public class TestObject5 {public static void main(String[] args) {// 创建对象(构造器是创建对象时使用),变量值默认为null,然后执行构造器,执行this.name=name的时候,执行的就是当前对象的name属性,即将dujian赋予this.nameBird bird = new Bird("dujian");System.out.println(bird.name);}
}class Bird{String name; // 成员变量也是有作用域的int age;public Bird(){}// 局部变量 == 标识符 == 见名知意 :成员变量的name不能使用其它,比如使用n代替,要与下方声明的一致,这样我们才能见名知意// 局部变量与成员变量发生冲突(变量名相同),局部变量一旦冲突,则距离作用域越近则优先级越高public Bird(String name){System.out.println("hello bird");// 当此时 name = name时,上方main入口打印bird.name为null,当使用this.name=name即可打印传进来的 "dujian"name = name; // 左值和右值都是局部变量的name,而此时局部变量name并不等同于成员变量的name,使用this使两者等同//this.name = name;}public Bird(String name, int age){this.name = name;this.age = age;}
}
package com.goshawk.object;/*** this关键字(类中出现)* 1、this修饰方法* 在类的方法中,如果调用属性和方法,如果没有显式的使用"this.",相当于是默认给了"this."* */
public class TestObject6 {public static void main(String[] args) {Pig pig = new Pig();pig.show();}
}class Pig{String name;int age;public void getName() {System.out.println(name);}public void setName() {name = "xiaozhu"; // 等同于this.name = "xiaozhu"}public void show() {this.getName(); // 等同于getName(); 即没有写this.的时候会默认加上}}
package com.goshawk.object;/*** this关键字(类中出现)* 1、this修饰构造器* 格式:* this(参数列表);* 注意:1> 只有在构造器中,可以通过this(参数列表)来调用类中的其它构造器。* 2> 一个类中最多能出现的this(参数列表)的次数是当前类中所有构造器的数量-1,避免造成死循环。。* 比如下方的例子,如果在空参构造使用this("a",2,"b");就会形成一个死循环;* 3> 对于this()的调用只能出现在构造方法的首行。* 4> 只能调用一次。** 2、为什么不能在方法中使用呢?* 因为在调用方法的时候,对象是已经创建了,而构造器的作用就是创建对象且给属性赋值。** 3、this(参数列表)的作用?* 实现代码复用。* */
public class TestObject7 {public static void main(String[] args) {Rabbit rabbit = new Rabbit("xiaobai",2,"ai");}
}class Rabbit{String name;int age;String gender;public Rabbit(){System.out.println("Rabbit()");}public Rabbit(String name){this();this.name = name;System.out.println("Rabbit(String name)");}// 带两个参数的构造器public Rabbit(String name, int age){// this.name = name;this(name);this.age = age;System.out.println("Rabbit(String name, int age)");}// 带三个参数的构造器public Rabbit(String name, int age, String gender){/** 这里注意:* this.name = name;与this.age = age;这两行代码与上方带两个参数的构造器重复了,那可否复用?* 如何复用?* this(); 表示调用类中的另外一个构造器* 当使用 this(name,age); 则代表调用了带两个参数的构造器,且这里的name与age传入进去* */// this.name = name;// this.age = age;this(name,age);this.gender = gender;System.out.println("Rabbit(String name, int age, String gender)");}}
面向对象的三大特性之一
public class TestEncapsulation{public static void main(String[] args){/**在对象的外部,为对象的属性赋值,可能存在非法数据的录入。*/Student s1 = new Student();s1.name = "tom";s1.age = 20000;s1.sex = "人妖";s1.score = 98;}
}class Student{String name;int age;String sex;double score;
}
private
(可将属性修饰为私有,仅本类可见)。public class TestEncapsulation{public static void main(String[] args){Student s1 = new Student();/**编译错误:私有属性在类的外部不可访问。*/s1.age = 20000;}}public Student{String name;int age;String sex;double score;
}
public class TestEncapsulation{public static void main(String[] args){/**以访问方法的形式,进而完成赋值与取值操作。问题:依旧没有解决到非法数据录入!*/Student s1 = new Student();s1.setAge(20000);System.out.println("s1.getAge()");s1.setSex("人妖");System.out.println("s1.getSex()");}}public Student{/**提供公共访问方法,以保证数据的正常录入。命名规范:赋值:setXXX() // 使用方法参数实现赋值取值:getXXX() // 使用方法返回值实现取值*/String name;private int age;private String sex;double score;public void setAge(int age){if(age>0&&age<=120){this.age = age;}else{this.age = 18;}}public int getAge(){return this.age;}public void setSex(String sex){if(sex.equals("男")||sex.equals("女"){this.sex = sex;}else{this.sex = "男";}}public String getSex(){return this.sex;}
}
public class TestEncapsulation{public static void main(String[] args){Student s1 = new Student();s1.setAge(20000);System.out.println("s1.getAge()");}}public Student{/**在公共的访问方法内部,添加逻辑判断,进而过滤掉非法数据,以保证数据安全。*/String name;private int age;String sex;double score;public void setAge(int age){// 指定有效范围if(age>0 && age<=120){ this.age = age;}else{this.age = 18; // 录入非法数据时的默认值}}public int getAge(){return this.age;}}
package com.goshawk.object;public class Animal {// 动物腿的数量// 权限修饰符 private(私有的 == public对立),只有类的内部才能访问被private修饰的属性。// 涉及到对属性赋值的动作,就全部封装到方法里面,让用户不能直接访问属性private int leg;/*** public,大家都能访问* 提供一个设置腿的数量方法* 约束腿的数量不能是奇数* */public void setLeg(int leg){if (leg%2==1){System.out.println("参数有误");return;}this.leg = leg;}/*** 获得腿数量的方法* @return*/public int getLeg(){return this.leg;}
}
package com.goshawk.object;/*** 封装* 面向对象有三大核心思想:继承、封装、多态* 1、冲突的出现* 如果说为对象的属性赋值,不加任何约束的话,很有可能会和现实世界造成冲突。比如:声明动物的腿数量为3;* 2、使用封装来解决这样的冲突* 把属性进行私有化,把对属性约束的逻辑体现在公共(public)的方法里。* 3、封装的含义:* 把功能封装在一个方法里面,一般来说,对属性的操作都是通过方法来实现的,而不是直接操作对象的属性。* 4、封装操作的一般实现步骤* 4.1> 要把属性私有化,隐藏起来--使用private进行修饰* 4.2> 提供公共的方法来操作私有的属性* 4.3> 在公共的方法里在其中加入一些约束逻辑** */
public class TestObject8 {public static void main(String[] args) {Animal a1 = new Animal();// 因为a1的leg属性被private修饰,于是访问不到(不能直接使用a1.name的形式调用,因为这样调用可能造成与世界不符的情况,或者说希望加上一些约束条件)。// a1.leg = 3;a1.setLeg(3);System.out.println(a1.getLeg());}
}
package com.goshawk.object;public class Person {private String name;// String name;private int age;public void setName(String name){// 属性没有私有化,使用这种方式避开这种约束,则是可以使用person.name这种形式来调用。// 如果属性进行私有化之后,只能调用这个方法来约束并进行调用if (name==null || "".equals(name)){System.out.println("参数有误");return;}this.name = name;}public void setAge(int age){if (age>200){System.out.println("参数有误");return;}}}
User
类(cardNo、identify、username、password、phone、balance
)Bank
类主要包括以下功能: initial
)login
)showMenu
)save
)、取款(withDraw
)、转账(trans
)、查询余额(query
)、修改密码(modifyPassword
)package com.goshawk.encap_1;
/*** 用户类* */
public class User {// 卡号private String cardNo;// 身份证号private String indentity;// 用户名private String username;// 密码private String password;// 电话private String phone;// 余额private double balance;public User(){}public User(String cardNo, String indentity, String username, String password, String phone, double balance) {this.cardNo = cardNo;this.indentity = indentity;this.username = username;this.password = password;this.phone = phone;this.balance = balance;}public String getCardNo() {return cardNo;}public void setCardNo(String cardNo) {this.cardNo = cardNo;}public String getIndentity() {return indentity;}public void setIndentity(String indentity) {this.indentity = indentity;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}
}
package com.goshawk.encap_1;import java.util.Scanner;/*** 银行类* */
public class Bank {// 保存用户的数组private User[] users = new User[5];// 保存个数private int size;// 初始化方法public void initial(){// 创建用户1User user1 = new User();user1.setCardNo("622208806601122");user1.setIndentity("158343423");user1.setUsername("李强");user1.setPassword("123456");user1.setPhone("18100000001");user1.setBalance(10000);// 创建用户2User user2 = new User("622208806601133", "1244324324", "赵武", "123456", "18100000002", 20000);// 放入数组中users[0] = user1;users[1] = user2;size = 2;// System.out.println("用户初始化完成");}public Bank(){initial();}// 用户登录public void login(){Scanner input = new Scanner(System.in);System.out.println("请输入卡号");String cardNo = input.next();System.out.println("请输入密码");String password = input.next();// 遍历数组User u = null; // u -> 保存找到的用户for (int i = 0;iif (users[i].getCardNo().equals(cardNo)&&users[i].getPassword().equals(password)){u = users[i];break;}}if (u!=null){// 登录成功 显示菜单System.out.println("登录成功");showMenu(u);}else {System.out.println("卡号或密码错误");}}// 显示菜单public void showMenu(User u){Scanner input = new Scanner(System.in);System.out.println("=================欢迎进入xxx银行系统==========【当前用户:"+u.getCardNo() + "】");do {System.out.println("=============1.存款 2.取款 3.转账 4.查询余额 5.修改密码 0.退出=============");int choice = input.nextInt();switch (choice) {case 1:this.save(u);break;case 2:this.withDraw(u);break;case 3:this.trans(u);break;case 4:this.query(u);break;case 5:this.modifyPassword(u);break;case 0:return;default:break;}} while (true);}/*** 存款* @param u*/public void save(User u){Scanner input = new Scanner(System.in);System.out.println("请输入存款金额");double m = input.nextDouble();if (m > 0){u.setBalance(u.getBalance()+m);System.out.println("存钱成功:余额"+u.getBalance());}else {System.out.println("存钱失败,请重新输入");}}/*** 取款* @param u*/public void withDraw(User u){Scanner input = new Scanner(System.in);System.out.println("请输入取款金额");double m = input.nextDouble();if (m > 0){if (u.getBalance()>m) {u.setBalance(u.getBalance() - m);System.out.println("取款成功:余额" + u.getBalance());}else {System.out.println("余额不足");}}else {System.out.println("取款失败,请重新输入");}}/*** 转账* @param u*/public void trans(User u){Scanner input = new Scanner(System.in);System.out.println("请输入目标转账卡号");String cardNo = input.next();System.out.println("请输入转账金额");double m = input.nextDouble();// 判断目标卡号是否存在User toUser = null;for (int i = 0; i < size; i++) {if (users[i].getCardNo().equals(cardNo)) {toUser = users[i];break;}}// 判断存在目标卡号if (toUser!=null){if (u.getBalance()>m){// 转账 自己账户扣钱u.setBalance(u.getBalance()-m);// 目标账户加钱toUser.setBalance(toUser.getBalance()+m);System.out.println("转账成功");}else {System.out.println("转账失败,余额不足");}}else {System.out.println("目标卡号不存在,请重新输入");}}/*** 查询余额* @param u*/public void query(User u){System.out.println("卡号:"+u.getCardNo()+" 用户名:"+u.getUsername()+" 余额:"+u.getBalance());}/*** 修改密码* @param u*/public void modifyPassword(User u){Scanner input = new Scanner(System.in);System.out.println("请输入请的密码");String newpassword = input.next();if (newpassword.length() == 6) {u.setPassword(newpassword);System.out.println("修改成功");}else {System.out.println("输入密码不符合要求");}}
}
package com.goshawk.encap_1;public class TestBank {public static void main(String[] args) {/*** 622208806601122* */Bank bank = new Bank();bank.login();}
}
{ }
括起来package com.goshawk.object;public class Teacher1 {private String name;// 构造代码块{System.out.println("构造代码块");}public Teacher1(){System.out.println("构造器");}// 普通代码块public String getName(){int a = 10;int b = 20;return name+a+b;}
}
package com.goshawk.object;/*** 代码块* 分类:* 1、普通(局部)代码块:定义在方法的内部* 2、构造代码块:跟床加你对象相关的代码块,与构造器相同,也起到初始化对象的作用。* 构造代码块和构造器,谁先谁后?构造代码块会早于构造器,先执行。* 3、静态代码块* 4、同步代码块** */
public class TestObject9 {public static void main(String[] args) {Teacher1 t1 = new Teacher1();}
}
static
(静态成员、类加载)static
)可以修饰属性和方法。static
关键字的介绍如果说要想使用某一个工具类的方法,目前只能先给工具类创建对象才能使用其中的方法。显然这样有些复杂。
那么要如何简化呢?
直接在方法前面加上static,于是可以直接通过"类名.静态方法"
的方式来调用,而不需要创建对象。
演示:
package com.goshawk.object;/*** 数学计算的工具类*/
public class MyMath {/*** 实现两数相加(静态方法)* @param a* @param b* @return*/public static int add(int a,int b){return a+b;}
}
package com.goshawk.object;/*** 静态 static* 1、static的介绍* 如果说要想使用某一个工具类的方法,目前只能先给工具类创建对象才能使用其中的方法。显然这样有些复杂。* 如何简化呢?* 直接在方法前面加上static,于是可以直接通过"类名.静态方法"的方式来调用,而不需要创建对象。** 2、static在类加载的过程中的变化* 所有使用static修饰的静态部分,都会随着类的加载而加载进元空间(方法区)。类中静态成员,在内存中只有一份。这一份是共用的。* */
public class TestObject10 {public static void main(String[] args) {// 实现两数相加// MyMath math = new MyMath();// int result = math.add(10, 20);int result = MyMath.add(10, 20);System.out.println(result);}
}
类中静态的成员包括:
package com.goshawk.object;public class SportMan {private String name;private int age;// 静态的属性==类变量 => 可以直接通过类名.类变量的方式来访问static String nation;// private String nation;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;}@Overridepublic String toString() {return "SportMan{" +"name='" + name + '\'' +", age=" + age + '\'' +", nation=" + nation +'}';}// public String getNation(){
// return nation;
// }
//
// public void setNation(String nation){
// this.nation = nation;
// }
}
package com.goshawk.object;/*** static修饰属性* 特点:* 1> 类的静态属性==类变量,=> 可以直接通过类名.类变量的方式来访问。* 2> 类变量在内存中只有一份,对象1修改了该属性,会影响其它对象对该属性值。* */
public class TestObject11 {public static void main(String[] args) {// 设置类变量,此时所有的对象都共用这一份变量SportMan.nation = "China";// 举办一个省级比赛SportMan s1 = new SportMan();s1.setName("小明");s1.setAge(20);// s1.setNation("China");SportMan s2 = new SportMan();s2.setName("小红");s2.setAge(22);// s1.setNation("China");SportMan s3 = new SportMan();s3.setName("小李");s3.setAge(23);// s3.setNation("China");System.out.println(s1);System.out.println(s2);System.out.println(s3);}
}
package com.goshawk.static_1;public class Student {String name;int age;// 学生数量 == 静态属性,属于整个类共有的属性static int count;public void show(){System.out.println(name + ">>>" + age);}
}
package com.goshawk.static_1;public class TestStudent {public static void main(String[] args) {Student s1 = new Student();s1.name = "小明";s1.age = 21;Student s2 = new Student();s2.name = "小赵";s2.age = 22;s1.show();s2.show();// 调用静态类名.静态属性名Student.count = 50;// s1.count = 100; 不建议使用System.out.println("学生数量:"+Student.count);}
}
package com.goshawk.static_1;public class Teacher {String name;int age;double salary; // 工资// 保存对象创建的次数static int count = 0;public Teacher(){// Teacher.count++;count++;}public void show(){System.out.println(name + "--->" + age + "--->" + salary);}
}
package com.goshawk.static_1;public class TestTeacher {public static void main(String[] args) {System.out.println("对象创建之前次数:" + Teacher.count);Teacher t1 = new Teacher();Teacher t2 = new Teacher();Teacher t3 = new Teacher();System.out.println("对象创建之后次数:" + Teacher.count);}
}
public class TestStaticMethod {public static void main(String[] args) {// 可在其他类中,通过 类名.静态方法名 访问。MyClass.method1();}
}class MyClass{public static void method1(){Ststem.out.println("MyClass static method1()");// 可在本类中,通过静态方法名访问method2();}// 由static修饰的静态方法public static void method2(){Ststem.out.println("MyClass static method2()");}
}
Arrays.copyOf();
Arrays.sort();
Math.random();
Math.sqrt();
this
或是super
关键字。package com.goshawk.object;/*** 数学计算的工具类*/
public class MyMath {// int num = 10;static int num = 10;/*** 实现两数相加(静态方法)* @param a* @param b* @return*/public static int add(int a, int b){System.out.println(a+b);return a+b;}public void show(){System.out.println("普通方法...");}public static int mul(int a, int b){// 在静态方法使用非静态成员会报错,因为静态的部分的加载是早于对象的创建// return a*b*numadd(a, b);return a*b*num;}
}
package com.goshawk.object;/*** static修饰方法* 1、类方法* static修饰方法称为类方法。* 直接通过"类名.类方法()" 来调用即可。** 2、注意事项* 2.1> 类方法的使用往往是直接通过类来调用,而非通过创建对象来调用。* 2.2> 类方法中不能出现类中的普通属性(成员变量),因为类方法的加载早于对象的创建。只有对象创建了,对象的属性才会存在。* 也就是说,类方法中的变量除了局部变量以外,只能是类变量。* 2.3> 类方法中不能出现出现this关键字,因为this描述的是当前对象,类方法的加载是早于对象的创建。* */
public class TestObject12 {public static void main(String[] args) {int result = MyMath.mul(10, 5);System.out.println(result);}
}
/**
类加载时,触发静态代码块的执行(仅一次)。
执行地位:静态属性初始化之后。
作用:可为静态属性赋值,或必要的初始行为。
*/
public class TestStaticBlock{public static void main(String[] args){MyClass.method();}
}class MyClass{static String sField = "静态属性";static{System.out.println(sField);System.out.println("静态代码块");}public static void method(){/**无代码只为触发静态属性的初始化和静态代码块的执行*/}
}
package com.goshawk.static_1;public class Person {String name;// 静态成员 人的最大数量static int max=0;// 静态代码块// 类加载的时候,则执行静态代码块,只执行一次(即使创建了多个对象,也是执行一次)static {max = 10000;System.out.println("人的最大数量:"+max);}// 静态方法public static void method(){}
}
package com.goshawk.static_1;public class TestPerson {public static void main(String[] args) {// Person p; // 注意此时是不会加载静态代码块的Person p = new Person(); // 触发方法一:创建对象// Person.method(); // 触发方式二:调用静态方法}
}
package com.goshawk.object;public class MyArrays {// 类变量public static int num=10;// 需求:对类变量进行初始化// 静态代码块什么时候执行?static {num=20;System.out.println("静态代码块,打印num:"+num);}public static int getNum(){return num;}public static void setNum(int num){MyArrays.num = num;}
}
package com.goshawk.object;/*** static修饰代码块* 1、静态代码块* 应用场景:* 用于对一个类中的类变量进行初始化** 2、使用格式* 在类中: static{静态代码块中的代码}** 3、当类加载的时候,静态代码块要被执行。* */
public class TestObject13 {public static void main(String[] args) {// 需求:在加载类变量的时候,类变量就被初始化了。System.out.println(MyArrays.getNum());}
}
this
关键字的问题this
关键字,因为静态方法调用的时候,不需要对象。this
关键字,因为非静态方法调用的时候必须要有对象。JVM
首次使用某个类时,需通过CLASSPATH
查找该类的.class
文件。.class
文件中对类的描述信息加载到内存中,进行保存。 Class.forName
(全限定名。)static
的总结static
修饰的成员为静态成员,无需创建对象,可直接通过类名访问。this
或者super
。Inheritance
)面向对象的三大特性之一
从生活中的继承,我们可以明白,继承就是从前辈手里获取一些好处
程序中的继承
is a
的关系(比如:Dog is an Anima
==> 成立) Dog
:子类、派生类Animal
:父类、超类is a
的关系。
Object
类(万物皆对象的概念)。实战:可根据程序需要使用到的多个具体类,进行共性抽取,进而定义父类。
父类抽取的案例
package com.goshawk.Inheritance;/*** 父类*/
public class Animal {// 品种String breed;// 年龄int age;// 性别String sex;// 吃public void eat(){System.out.println("吃饭");}// 睡public void sleep(){System.out.println("睡觉");}
}
package com.goshawk.Inheritance;
/*** 狗类* */
public class Dog extends Animal{// 毛色String furColor;// 跑public void run(){System.out.println("跑");}
}
package com.goshawk.Inheritance;
/*** 鸟类* */
public class Bird extends Animal{// 毛色String furColor;// 飞public void fly(){System.out.println("飞");}
}
package com.goshawk.Inheritance;
/*** 蛇类* */
public class Snake extends Animal{// 爬public void climb(){System.out.println("爬");}
}
package com.goshawk.Inheritance;public class TestDog {public static void main(String[] args) {Dog wangcai = new Dog();wangcai.breed = "萨摩";wangcai.age = 2;wangcai.sex = "公";wangcai.furColor = "白色";wangcai.eat();wangcai.sleep();wangcai.run();}
}
class 子类 extends 父类{} // 定义子类时,显示继承父类
package com.goshawk.extend;public class Person {private String name;private int age;private String gender;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setGender(String gender) {this.gender = gender;}public String getName() {return name;}public int getAge() {return age;}public String getGender() {return gender;}public void eat(){}public void sleep(){}
}
package com.goshawk.extend;public class Teacher {// 作为人类的基本属性private String name;private int age;private String gender;// 作为老师,额外的属性private String schoolName;private String major;// 功能public void eat(){}public void sleep(){}// 额外的功能public void teach(){System.out.println("老师上课");}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setGender(String gender) {this.gender = gender;}public void setSchoolName(String schoolName) {this.schoolName = schoolName;}public void setMajor(String major) {this.major = major;}public String getName() {return name;}public int getAge() {return age;}public String getGender() {return gender;}public String getSchoolName() {return schoolName;}public String getMajor() {return major;}
}
package com.goshawk.extend;public class Teacher {// 作为人类的基本属性private String name;private int age;private String gender;// 作为老师,额外的属性private String schoolName;private String major;// 功能public void eat(){}public void sleep(){}// 额外的功能public void teach(){System.out.println("老师上课");}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setGender(String gender) {this.gender = gender;}public void setSchoolName(String schoolName) {this.schoolName = schoolName;}public void setMajor(String major) {this.major = major;}public String getName() {return name;}public int getAge() {return age;}public String getGender() {return gender;}public String getSchoolName() {return schoolName;}public String getMajor() {return major;}
}
package com.goshawk.extend;public class Person {private String name;private int age;private String gender;public Person(){System.out.println("public Person() >> 构造方法");}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setGender(String gender) {this.gender = gender;}public String getName() {return name;}public int getAge() {return age;}public String getGender() {return gender;}public void eat(){System.out.println("eat");}public void sleep(){System.out.println("sleep");}
}
package com.goshawk.extend;public class Teacher extends Person{// 作为老师,额外的属性private String schoolName;private String major;// 额外的功能public void teach(){System.out.println("老师上课");}public void setSchoolName(String schoolName) {this.schoolName = schoolName;}public void setMajor(String major) {this.major = major;}public String getSchoolName() {return schoolName;}public String getMajor() {return major;}
}
package com.goshawk.extend;public class Student extends Person{// 额外的属性private Long stuId;private String address;// 额外的功能public void study(){}public Long getStuId() {return stuId;}public String getAddress() {return address;}public void setStuId(Long stuId) {this.stuId = stuId;}public void setAddress(String address) {this.address = address;}
}
package com.goshawk.extend;
/*** 继承* 1、继承的目的* 在创建一个类时,可以通过继承,快速的获得该类中已经定义好的内容,而避免了重复定义(重复造轮子)。** 2、继承的使用* class 子类 extends 父类{}** */
public class Demo1 {public static void main(String[] args) {Teacher t1 = new Teacher();t1.setName("tom");t1.setAge(22);t1.eat();t1.setMajor("Java");t1.teach();System.out.println(t1.getName());}
}
/**
下述案例的子类Son所持有的属性和方法:int a;int b;int c;m1();m2();
*/
class Father{int a;int b;public void m1(){}
}class Son extends Father{int c;public void m2(){}
}
public class TestSuperKeyword{public static void main(String[] args){C c = new C();}
}class A{}
class B extends A{}
class C extends B{}
package com.goshawk.Inheritance_1;public class A {int num1;int num2;public A(){System.out.println("A的默认构造方法");}public void m1(){System.out.println("A类的m1方法");}
}
package com.goshawk.Inheritance_1;public class B extends A{int num3;public B(){System.out.println("B的默认构造方法");}public void m2(){System.out.println("B类的m2方法");}
}
package com.goshawk.Inheritance_1;public class TestB{public static void main(String[] args) {B b = new B();b.m1();b.m2();}
}
代码如下:
package com.goshawk.extend;public class Employee {private String name;private int age;private Long workerId;public String getName() {return name;}public int getAge() {return age;}public Long getWorkerId(){return workerId;}public void setWorkerId(Long workerId){this.workerId = workerId;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void sign(){System.out.println("打卡");}
}
package com.goshawk.extend;
/*** 程序员* */
public class Programmer extends Employee {public void coder(){System.out.println("程序员喜欢敲代码");}}
package com.goshawk.extend;public class HR extends Employee{public void recruit(){System.out.println("招聘");}
}
package com.goshawk.extend;public class Demo2 {public static void main(String[] args) {Programmer p1 = new Programmer();p1.sign();p1.coder();}
}
private
修饰的属性和方法。 package
中时,default
修饰的属性和方法。本类 | 同包 | 非同包子类 | 其他(非同包非子类) | |
---|---|---|---|---|
private | ✓ | × | × | × |
default (默认的) | ✓ | ✓ | × | × |
protected (保护的) | ✓ | ✓ | ✓ | × |
public | ✓ | ✓ | ✓ | ✓ |
✓:可用
×:不可用
从上到下:严 --> 宽
注意:default
(默认的),而它是不用显示写出来的,如果写出来是会报错的。
public、protected
修饰属性在package_A
创建一个父类Animal
:
package com.goshawk.Inheritance;/*** 父类*/
public class Animal {// 品种public String breed;// 年龄protected int age;// 性别public String sex;// 吃public void eat(){System.out.println("吃饭");}// 睡public void sleep(){System.out.println("睡觉");}
}
在package_B
创建一个子类Cat
:
package com.goshawk.package_B;
package com.goshawk.package_A;
/*** 猫类* */
public class Cat extends Animal{String furColor;String hobby;public void playBall(){// 此时被保护的age是可以被调用的System.out.println(this.age);}
}
在package_B
创建一个测试文件TestCat
:
package com.goshawk.package_B;public class TestCat{public static void main(String[] args){Cat bosimao = new Cat();// baosimao.age = 2; 这里的用法是错误的,因为非同包非子类是不能被调用的。}
}
super指的是父类、超类、基类;
super描述的是 “父类的” ==== this描述的是"当前对象的";
在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问。
public class TestSuperKeyword{public static void main(String[] args){B b = new B();b.upload();}
}class A{/**父类具有上传文件的功能*/public void upload(){// 上传文件的100行逻辑代码}
}class B extends A{/**子类既要上传文件,又要更改文件名称,进而覆盖了父类的方法。但上传文件的逻辑代码相同,如何复用? 参考:10.3 super修饰方法*/public void upload(){// 上传文件的100行逻辑代码// 修改文件名称的1行代码}
}
super(参数列表);
package com.goshawk.supe;public class A {private String name;private int age;public A(){System.out.println("public A()");}public A(String name){this.name = name;System.out.println("public A(String name)");}public A(String name, int age){this.name = name;this.age = age;System.out.println("public A(String name, int age)");}
}
package com.goshawk.supe;public class B extends A{private String address;// 如果这里没有定义空参构造器,系统会默认提供如下的空参构造器,如果父类也没有定义空参构造器,会报错
// 那么要怎么办呢?
// 如果父类有定义带参的构造器,可以直接调用父类带参的构造器,比如:super(参数列表);
// public B(){
// super();
// }public B(){// 在调用父类的空参构造器super();System.out.println("public B()");}
}
package com.goshawk.supe;/*** super关键字* super指的是父类、超类、基类* super描述的是 "父类的" ==== this描述的是"当前对象的"*/
public class Demo1 {public static void main(String[] args) {B b = new B();}
}
/**
super():表示调用父类无参构造方法。
如果没有显示书写,隐式存在于子类构造方法的首行。
*/
class A{public A(){System.out.println("A类的无参构造方法")}
}class B extends A{public B(){super(); // 调用父类的无参构造方法(不写会默认调用。)System.out.println("B类的无参构造方法")}
}class C extends B{public C(){super();System.out.println("C类的无参构造方法")}
}public class TestSuperKeyword{public static void main(String[] args){new C();}
}// 执行new C()
// 首先打印:A类的无参构造方法
// 然后打印:B类的无参构造方法
// 最后打印:C类的无参构造方法
/**
super():表示调用父类无参构造方法。
super(实参):表示调用父类带参的构造方法。
*/
class A{public A(){System.out.println("A类的无参构造方法")}public A(int value){System.out.println("A类的带参构造方法")}
}class B extends A{public B(){super(); System.out.println("B类的无参构造方法")}public B(int value){super(value); System.out.println("B类的带参构造方法")}
}public class TestSuperKeyword{public static void main(String[] args){new B();new B(10);}
}// 先执行new B(),然后执行new B(10);
// 首先打印:A类的无参构造方法
// 然后打印:B类的无参构造方法
// 再然后打印:A类的带参构造方法
// 最后打印:B类的带参构造方法
package com.goshawk.Inheritance_1;public class A {int num1;int num2;public A(){System.out.println("A的默认构造方法");}public A(int num1, int num2){System.out.println("A的带参构造方法");this.num1 = num1;this.num2 = num2;}public void m1(){System.out.println("A类的m1方法");}
}
package com.goshawk.Inheritance_1;public class B extends A{int num3;public B(){super(); // 调用父类的无参构造方法(不写会默认调用。)System.out.println("B的默认构造方法");}public B(int num1, int num2, int num3){// super(); // 默认调用父类的无参构造方法super(num1, num2); // 调用父类的带参构造方法System.out.println("B的带参构造方法");// 以下两行由于父类的带参构造方法存在(super(num1, num2)),所以省略
// this.num1 = num1;
// this.num2 = num2;this.num3 = num3;}public void m2(){System.out.println("B类的m2方法");}
}
package com.goshawk.Inheritance_1;/*** super调用父类的构造方法** super调用父类的带参构造方法*/
public class TestB{public static void main(String[] args) {B b = new B(100, 200, 300);b.m1();b.m2();}
}
package com.goshawk.supe;public class A {private String name;private int age;public A(String name){this.name = name;System.out.println("public A(String name)");}public A(String name, int age){this.name = name;this.age = age;System.out.println("public A(String name, int age)");}
}
package com.goshawk.supe;public class B extends A{private String address;public B(){// 使用super(参数列表)来指定调用父类中的某一个构造器super("abc");System.out.println("public B()");}
}
package com.goshawk.supe;/*** super关键字* super指的是父类、超类、基类* super描述的是 "父类的" ==== this描述的是"当前对象的"*/
public class Demo1 {public static void main(String[] args) {B b = new B();}
}
package com.goshawk.supe;public class Person {// 身份证号String id = "2002";String name;public void eat(){System.out.println("吃饭");}
}
package com.goshawk.supe;public class Student extends Person{// 学号private String id = "1001";public void getName(){// 这里的name为什么调用仍然是父类的name,因为子类没有声明name属性System.out.println(name);}public void getId(){System.out.println("子类ID属性:"+id);// 打印身份证号,使用super,显式的告知要调用父类的id属性System.out.println("父类ID属性:"+super.id);}
}
package com.goshawk.supe;/*** super修饰属性*/
public class Demo2 {public static void main(String[] args) {Student student = new Student();student.getId();}
}
public class TestSuperKeyword{public static void main(String[] args){B b = new B();b.print();}
}class A{int value = 10;
}class B extends A{int value = 20;public void print(){int value = 30;System.out.println(value); // 局部变量 打印 30System.out.println(this.value); // 本类的实例变量 打印 20System.out.println(super.value); // 父类的实例变量 打印 10}
}
public class TestSuperKeyword{public static void main(String[] args){B b = new B();b.upload();}
}class A{/**父类具有上传文件的功能*/public void upload(){// 上传文件的100行逻辑代码}
}class B extends A{public void upload(){// 上传文件的100行逻辑代码// 修改文件名称的1行代码// super关键字可在子类中访问父类的方法。// 使用"super."的形式访问父类的方法,进而完成在子类中的复用;再叠加额外的功能代码,组成新的功能。super.upload();}
}
super.方法(); // 在子类类中的方法中使用
package com.goshawk.supe;public class Person {// 身份证号String id = "2002";String name;public void eat(){System.out.println("吃饭");}public void sleep(){System.out.println("睡觉");}
}
package com.goshawk.supe;public class Student extends Person{// 学号private String id = "1001";public void getName(){// 这里的name为什么调用仍然是父类的name,因为子类没有声明name属性System.out.println(name);}public void getId(){System.out.println("子类ID属性:"+id);// 打印身份证号,使用super,显式的告知要调用父类的id属性System.out.println("父类ID属性:"+super.id);}public void eat(){System.out.println("学生要吃有营养的东西");}public void show(){// eat(); // 等同于this.eat();调用子类的方法// 调用父类的方法super.eat();}
}
package com.goshawk.supe;/*** super修饰方法* 1、格式* super.方法();* 在子类类中的方法使用。* 此时就是指明调用父类中的方法。** 2、方法重写的应用场景* 为什么要用super调用方法,就是因为子类中出现了和父类中的同名方法(方法名相同、参数列表完全相同)。* 如果需要使用父类的同名方法,那么就需要在子类中使用super来调用。* 3、父类的静态方法不能被重写。*/
public class Demo3 {public static void main(String[] args) {Student s1 = new Student();s1.show();}
}
this
表示当前对象引用,调用本类(包括继承)的属性、方法、本类构造方法。supper
表示父类对象引用,调用父类的属性、方法、构造方法。class A{public A(){System.out.println("A-无参构造");}public A(int value){System.out.println("A-有参构造");}
}class B extends A{public B(){super();System.out.println("B-无参构造");}public B(int value){this(); // super(); 注意不能同时存在System.out.println("B-有参构造");}
}public class TestSuperKeyword{public static void main(String[] args){new B(10);}
}/**
this或super使用在构造方法中时,都要求在首行。
当子类构造中使用了this();或者this(实参),
即不可再同时书写super();或者super(实参),
会由this()指向的构造方法完成super()的调用。如上述案例运行结果:
A-无参构造
B-无参构造
B-有参构造
*/
Override
)package com.goshawk.overriding;public class Person {private String name;public void eat(){System.out.println("吃饭");}}
package com.goshawk.overriding;public class Student extends Person{// 会得到eat的方法public void eat(){System.out.println("吃有营养的晚餐");}
}
package com.goshawk.overriding;/*** 方法的重写* 1、为什么需要方法的重写* 当子类继承父类时,父类的方法对子类不适用,于是子类可以重写父类的方法。** 2、方法的重写和方法的重载之间区别* - 方法的重载:方法名相同,参数列表不同,跟返回值和权限修饰符无关。* - 方法的重写:子类要去覆盖掉父类中的方法,就要防止把覆盖变成了重载的失误。(子类重写的方法的方法名、参数列表、返回值类型必须和父类的完全一致),且访问权限修饰符不能小于父类(比如:public > private)。** 3、父类的静态方法不能被重写。*/
public class Demo1 {public static void main(String[] args) {Student stu = new Student();stu.eat();}
}
程序员敲代码的方式,最开始的时候使用notepad++写代码,后来经过升级改造,使用了eclipse编程工具写代码,有的升级到IDEA
package com.goshawk.overriding;public class Programmer {private String name;private String major;public void codingTool(){System.out.println("Notepad++");}
}
package com.goshawk.overriding;public class ProgrammerPlus extends Programmer{@Overridepublic void codingTool() {System.out.println("Eclipse");}
}
package com.goshawk.overriding;public class ProgrammerMaster extends Programmer{@Overridepublic void codingTool() {System.out.println("IDEA");}
}
package com.goshawk.overriding;public class Demo2 {public static void main(String[] args) {Programmer programmer = new Programmer();programmer.codingTool();ProgrammerPlus programmerPlus = new ProgrammerPlus();programmerPlus.codingTool();ProgrammerMaster programmerMaster = new ProgrammerMaster();programmerMaster.codingTool();}
}
老师都有授课的能力,但每个老师授课的风格内容不一样,编程模拟
package com.goshawk.overriding;public class Teacher {public void teach(){System.out.println("老师认真的授课");}
}
package com.goshawk.overriding;public class SportTeacher extends Teacher{@Overridepublic void teach() {System.out.println("演示运动项目");}
}
package com.goshawk.overriding;public class EnglishTeacher extends Teacher{@Overridepublic void teach() {System.out.println("教授生动的课程");}
}
package com.goshawk.overriding;public class Demo3 {public static void main(String[] args) {SportTeacher sportTeacher = new SportTeacher();sportTeacher.teach();EnglishTeacher englishTeacher = new EnglishTeacher();englishTeacher.teach();}
}
@Override
?Polymorphism
)面向对象的三大特性之一
is a
关系时,即形成多态。Animal a = new Dog();// Animal a:父类引用(引用类型)
// new Dog():子类对象(对象类型)// 1、从逻辑上讲:Dog is a Animal
// 2、从语法上讲:自动类型转换
package com.goshawk.Inheritance_1;/*** 父类*/
public class Animal {// 品种String breed;// 年龄protected int age;// 性别public String sex;// 吃public void eat(){System.out.println("吃饭");}// 睡public void sleep(){System.out.println("睡觉");}
}
package com.goshawk.Inheritance_1;import com.goshawk.Inheritance_1.Animal;/*** 狗类* */
public class Dog extends Animal {// 毛色String furColor;@Overridepublic void eat(){System.out.println("狗狗开始吃狗粮");}}
package com.goshawk.Inheritance_1;import com.goshawk.Inheritance_1.Animal;/*** 鸟类* */
public class Bird extends Animal {// 毛色String furColor;@Overridepublic void eat() {System.out.println("鸟儿开始吃虫子");}// 飞public void fly(){System.out.println("飞");}
}
package com.goshawk.Inheritance_1;public class TestAnimal {public static void main(String[] args) {// 1、从逻辑上讲:Dog is a Animal// 2、从语法上讲:自动类型转换Animal a = new Dog();a.age = 2;a.breed = "萨摩";a.sex = "公";a.eat();Animal b = new Bird();b.eat();}
}
场景一
使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。
package com.goshawk.Inheritance_1;/*** 主人类*/
public class Master {String name;/*** 喂狗* @param dog*/public void feed(Dog dog){System.out.println(this.name + "喂食");dog.eat();}/*** 喂鸟*/public void feed(Bird bird){System.out.println(this.name + "喂食");bird.eat();}/*** 使用多态优化*/public void feed(Animal animal){System.out.println(this.name + "喂食");animal.eat();}
}
场景二
使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。
/**
Master.java
*/
package com.goshawk.Inheritance_1;/*** 主人类*/
public class Master {String name;/*** 购买动物*/public Animal buy(int type) {Animal animal = null;if (type == 1){animal = new Dog();}else if(type == 2){animal = new Bird();}return animal;}
}/**
TestMaster.java
*/
package com.goshawk.Inheritance_1;import java.util.Scanner;public class TestMaster2 {public static void main(String[] args) {System.out.println("=============欢迎来到动物市场=============");System.out.println("=============1.买狗狗 2. 买鸟儿=============");System.out.println("请选择");Scanner input = new Scanner(System.in);int choice = input.nextInt();Master master = new Master();Animal animal = master.buy(choice);if (animal!=null){System.out.println("购买成功");}else {System.out.println("购买失败");}}
}
向上转型:父类的引用指向子类对象的实体。
多态使用的情况下,编译时看等号的左边,运行时看等号的右边。
因此没有办法通过多态来调用到子类独有的方法。
如果一定要调用独有的方法,就需要通过向下转型来实现。
public class TestConvert{public static void main(String[] args){// 父类引用中保存真实子类对象,称为向上转型(即多态核心概念)。// 注意:仅可调用Animal中所声明的属性和方法。Animal a = new Dog();}
}class Animal{public void eat(){System.out.println("动物在吃东西");}
}class Dog extends Animal{public void eat(){System.out.println("狗在吃狗粮");}
}
向下转型时,如果父类引用中的子类对象类型和目标类型不匹配,则会发生类型转换异常。
Exception in thread "main" java.lang.ClassCastException
如下:
class Animal{public void eat(){System.out.println("动物在吃东西");}
}class Dog extends Animal{public void eat(){System.out.println("狗在吃狗粮");}
}class Cat extends Animal{public void eat(){System.out.println("猫在吃猫粮");}
}public class TestConvert{public static void main(String[] args){/**在进行使用多态进行向下转换时,没有转换回子类的真实类型。比如:父类为Animal,实际上子类的类型为Dog,但是在进行向下转型的时候却转成Cat,这样就不能调用原本Dog这个子类独有的属性和方法。*Animal a = new Dog();Cat cat = (Cat)a;}
}
public class TestConvert{public static void main(String[] args){// 通过a只能调用父类的属性和方法或者子类重写的方法,就不能调用子类特有的属性和方法,那么要怎么办呢?Animal a = new Dog();// 将a强转成Dog,只能这样才能调用子类特有的属性和方法。Dog dog = (Dog)a;}
}class Animal{public void eat(){System.out.println("动物在吃东西");}
}class Dog extends Animal{public void eat(){System.out.println("狗在吃狗粮");}
}
在向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性。
向下转型可能涉及到数据类型转换的异常,因此在做向下转型之前,先做一次 instanceof 数据类型的判断。
将父类引用指向子类对象再转回子类类型。
这种转型是有风险的,因为是强制性,一旦转向的类型跟这个对象不匹配,就会报错。java.lang.ClassCastException
(类型转换异常,属于运行时的异常)
语法:
引用 instanceof 类型 // 返回boolean(布尔值)类型结果,如果匹配则返回true。
//if (对象 instanceof 类) ==> 对象是否是该类的实体
public class TestConvert{public static void main(String[] args){Animal a = new Dog();// 当 a 引用中存储的对象类型确实为Dog时,再进行类型转换,进而调用Dog中的独有方法。if (a instanceof Dog){Dog dog = (Dog)a;dog.eat();}else if(a instanceof Cat){Cat cat = (Cat)a;cat.eat();}}
}
package com.goshawk.Inheritance_1;/*** 父类*/
public class Animal {// 品种String breed;// 年龄protected int age;// 性别public String sex;// 吃public void eat(){System.out.println("吃饭");}// 睡public void sleep(){System.out.println("睡觉");}
}
package com.goshawk.Inheritance_1;import com.goshawk.Inheritance_1.Animal;/*** 鸟类* */
public class Bird extends Animal {// 毛色String furColor;@Overridepublic void eat() {System.out.println("鸟儿开始吃虫子");}// 飞public void fly(){System.out.println("飞");}
}
package com.goshawk.Inheritance_1;import com.goshawk.Inheritance_1.Animal;/*** 狗类* */
public class Dog extends Animal {// 毛色String furColor;@Overridepublic void eat(){System.out.println("狗狗开始吃狗粮");}public void run(){System.out.println("跑");}}
package com.goshawk.Inheritance_1;/*** 主人类*/
public class Master {String name;/*** 喂狗* @param dog*/public void feed(Dog dog){System.out.println(this.name + "喂食");dog.eat();}/*** 喂鸟*/public void feed(Bird bird){System.out.println(this.name + "喂食");bird.eat();}/*** 使用多态优化:喂狗和喂鸟*/public void feed(Animal animal){System.out.println(this.name + "喂食");animal.eat();}/*** 购买动物*/public Animal buy(int type) {Animal animal = null;if (type == 1){animal = new Dog();}else if(type == 2){animal = new Bird();}return animal;}
}
package com.goshawk.Inheritance_1;import java.util.Scanner;public class TestMaster2 {public static void main(String[] args) {System.out.println("=============欢迎来到动物市场=============");System.out.println("=============1.买狗狗 2. 买鸟儿=============");System.out.println("请选择");Scanner input = new Scanner(System.in);int choice = input.nextInt();Master master = new Master();Animal animal = master.buy(choice);if (animal!=null){System.out.println("购买成功");if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.run();} else if (animal instanceof Bird) {Bird bird = (Bird) animal;bird.fly();}}else {System.out.println("购买失败");}}
}
package com.goshawk.oop;public class Person {private String name;private int age;public Person() {super();}public Person(String name, int age) {this.name = name;this.age = age;}public void dancing(){System.out.println("跳舞");}public String getName() {return name;}public int getAge() {return age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}}
package com.goshawk.oop;public class Man extends Person{@Overridepublic void dancing() {System.out.println("男生跳街舞");}/*** 男生独有的方法*/public void sporting(){System.out.println("男生喜欢运动");}
}
package com.goshawk.oop;public class Woman extends Person{@Overridepublic void dancing() {System.out.println("女生跳民族舞");}public void shopping(){System.out.println("购物");}
}
package com.goshawk.oop;/*** 多态* 1、定义* 一种事物的多种形态** 2、多态出现的场景* 2.1> 父类的引用指向子类对象的实体 == 也称为向上转型* - 多态使用的情况下,编译时看等号的左边,运行时看等号的右边。* - 因此没有办法通过多态来调用到子类独有的方法。* - 如果一定要调用独有的方法,就需要通过向下转型来实现。* 2.3> 接口的引用指向接口实现类的实体** 3、向上转型和向下转型(instanceof 向下)* 3.1> 向上转型:父类的引用指向子类对象的实体* 3.2> 向下转型:强制把子类的对象(的父类的引用)转换成子类的引用。* 向下转型可能涉及到数据类型转换的异常,因此在做向下转型之前,先做一次 instanceof 数据类型的判断。* 4、instanceof的使用(产生一个布尔值的结果)* 格式:* 对象 instanceof 类 ==> 对象是否是该类的实体*/
public class Demo1 {public static void main(String[] args) {Man man = new Man();Woman woman = new Woman();// 场景一:父类的引用指向指向子类对象的实体Person person = new Man();Person person1 = new Woman();// 男生进入到舞厅跳舞enter(man);// 女生进入到舞厅跳舞enter(woman);}/*** 今天晚上有一个聚会,大家去舞厅跳舞。进入到舞厅的人。如果是男生就跳男生的舞,如果是女生就跳女生的舞。*/
// public static void enter(Man man){
// man.dancing();
//
// }
//
// public static void enter(Woman woman){
// woman.dancing();
//
// }// 父类的引用指向了子类对象的实体// Person person = new Man();public static void enter(Person person){person.dancing();}
}
package com.goshawk.oop;/*** 多态*/
public class Demo2 {public static void main(String[] args) {Person person = new Man();Man man = new Man();// 实际上执行的是Man对象中的dancing方法person.dancing();// 多态使用的情况下,编译时看等号的左边,运行时看等号的右边// person.sporting(); 这样调用会报错,也就说,编译时找的是Person(),运行时找的是Man()man.sporting();}}
package com.goshawk.oop;/*** 多态*/
public class Demo3 {public static void main(String[] args) {// 向上转型 子类对象赋予给父类 == 父类的引用指向子类对象的实体// 父类类型的变量引用子类类型的实例对象Person p1 = new Man();Person p2 = new Woman();show(p1);show(p2);}// 向下转型 ==> 强制类型转换// 需要通过关键字(instanceof)先做一次判断/*** 如果是person参数是男生的话,就调用sporting方法;如果是女生的话就调用shopping方法* @param person*/public static void show(Person person){
// // person.sporting(); 这里会报错,因为show方法的形参类型是Person,而传进来的实参类型为Man(),所以这里需要进行强转
// Man man = (Man) person; // new Man()
// man.sporting();// instanceof左边为对象,右边为类;可以理解为 person对象属于Man的实例if (person instanceof Man){Man man = (Man) person;man.sporting();}else if (person instanceof Woman){Woman woman = (Woman) person;woman.shopping();}}}
package com.goshawk.oop;/*** 多态的测试题* 动物都有吃饭的功能,但是小狗吃的是狗粮,小猫吃的是猫粮,当我们将小猫小狗体貌特征遮盖住的时候,如何判定吃东西的是小猫还是小狗?* 如果是小猫,就调用小猫独有的粘人功能,如果是小狗,就调用小狗独有的看门功能。*/
public class Demo4 {public static void main(String[] args) {Animal a1 = new Cat();Animal a2 = new Dog();checkAnimal(a1);checkAnimal(a2);}public static void checkAnimal(Animal animal){if (animal instanceof Cat){animal.eat();Cat cat = (Cat) animal;cat.show();}if (animal instanceof Dog){animal.eat();Dog dog = (Dog) animal;dog.watch();}}}class Animal{public int eat(){System.out.println("动物吃饭");return 0;}
}class Cat extends Animal{@Overridepublic int eat() {System.out.println("小猫吃猫粮");return 1;}public void show(){System.out.println("粘人");}
}class Dog extends Animal{@Overridepublic int eat() {System.out.println("小狗吃狗粮");return 2;}public void watch(){System.out.println("看门");}
}
package com.goshawk.oop;public class Demo6 {public static void main(String[] args) {A a = new B(); // 多态a.show();B b = new C();b.show(); // C()的show()}
}class A{public void show(){show2();}public void show2(){System.out.println("我");}
}class B extends A{public void show2(){System.out.println("是");}
}class C extends B{public void show(){super.show(); // B类的show}public void show2(){System.out.println("谁");}
}
package com.goshawk.oop;public class Demo5 {public static void main(String[] args) {Father father = new Son();System.out.println(father.getName()); // 小明System.out.println(father.name); // 小红 属性不存在被覆盖}
}class Father{String name = "小红";public String getName() {return name;}public void setName(String name) {this.name = this.name;}
}class Son extends Father{String name ="小明";public String getName() {return this.name;}public void setName(String name) {this.name = name;}
}
final
表示最终的,无法被修改的。final
修饰的特点final
修饰类final
修饰类:此类不能被继承。 String、Math、System
均为final
修饰的类,不能被继承。package com.goshawk.finaldemo;public final class Car {String brand;String color;public void run(){System.out.println("汽车正在前进");}
}
final
修饰方法final
修饰方法:此方法不能被覆盖(重写),但是可以被继承。package com.goshawk.finaldemo;public class Car {String brand;String color;// final方法,最终方法,不能被重写覆盖,但是可以被继承public final void run(){System.out.println("汽车正在前进");}
}
package com.goshawk.finaldemo;public class SmallCar extends Car {}
package com.goshawk.finaldemo;public class TestCar {public static void main(String[] args) {SmallCar smallCar = new SmallCar();smallCar.run();}
}
final
修饰局部变量 ,则称为局部常量。final
修饰变量:此变量值不能被改变(常量)。final
可以修饰形参。基本数据类型,是值不能被改变。
引用数据类型,是地址值不能被改变,对象中的属性可以改变。
package com.goshawk.finaldemo;public class Person {private String name = "小明";public String getName(){return name;}public void setName(String name){this.name = name;}
}
package com.goshawk.finaldemo;/*** final修饰引用数据类型的变量,此时该变量的属性值能否改变?可以修改,前提是该对象的该属性没有被final修饰。*/
public class Demo3 {public static void main(String[] args) {final Person person = new Person();person.setName("小李");// person = new Person(); 这里不能改System.out.println(person.getName());}
}
public class TestFinal{public static void main(String[] args){final int num = 10;// 所有final修饰的变量只能赋值一次,值不允许改变。// num =20; 错误:无法为最终变量num分配值}
}
final
修饰实例变量。public class TestFinal{public static void main(String[] args){new Student();}
}class Student{final String name; // = "Tom"public Student(){// name = "Tom";}
}
package com.goshawk.finaldemo;public class Car {final String brand; // 实例常量,不再提供默认值,必须赋值,并且只能赋值一次。public Car(){this.brand = "宝马";}public Car(String brand) {this.brand = brand;}String color;// final方法,最终方法,不能被重写覆盖,但是可以被继承public final void run(){System.out.println("汽车正在前进");}
}
public class TestFinal{public static void main(String[] args){System.out.println(Student.SCHOOL_NAME);}
}class Student{static final String SCHOOL_NAME = "中心小学";}
public class Car {final static String ADDRESS;static {ADDRESS = "德国";}}
package com.goshawk.finaldemo;public class Student {String name;
}
package com.goshawk.finaldemo;import java.util.Arrays;public class TestStudent {public static void main(String[] args) {// final修饰基本类型final int num = 20;// num = 30; final修饰基本类型(值不可改变)final int[] nums = new int[] {11, 22, 33}; // nums不能再赋值,但是里面的元素是可以改变的// nums = new int[5];nums[0] = 100;System.out.println(Arrays.toString(nums));final Student s = new Student();// 这里的s不能再赋值,但是可以s的属性进行赋值// s = new Student(); final修饰引用类型(地址不可改变)s.name = "abc";System.out.println(s.name);}
}
package com.goshawk.finaldemo;/*** final修饰类:也称为太监类(没有子孙)。* 应用场景:这个类不希望再被修改。* */
public final class A {private String name;public void eat(){}
}
package com.goshawk.finaldemo;/**** final修饰属性*/
public class B {// 变量不能再被改变 == 常量final int a = 10;public void add(int b){// a = 20; // 这里会报错,因为不能对常量赋值int result = this.a + b;System.out.println(result);}
}
package com.goshawk.finaldemo;/**** final修饰属性*/
public class C {/**// 第一种初始化的方式final int MY_NUM = 10; // 如果不初始化,会报错,在这里即等同赋值*//**// 第二种初始化的方式final int MY_NUM_1;{MY_NUM_1 = 10;}*//**// 第三种初始化的方式final int MY_NUM_2;public C(){MY_NUM_2 = 10;}*//**// 第四种初始化的方式final int MY_NUM_3;public C(int a){MY_NUM_3 = a;}*/}
package com.goshawk.finaldemo;public class D {final static String MONDAY="星期一";
}
package com.goshawk.finaldemo;public class E {public final void eat(){System.out.println("吃饭");}
}
package com.goshawk.finaldemo;public class F extends E{
// 父类E的eat加了final,因此不能被重写
// @Override
// public void eat(){
// System.out.println("吃饭");
// }
}
package com.goshawk.finaldemo;/*** final关键字* 1、定义* final表示最终的* 2、final修饰类:也称为太监类(没有子孙)。* 应用场景:这个类不希望再被修改。** 3、final修饰变量* 3.1> 此时改变量就是常量,不能再被赋值(改变)。3.2> 常量必须赋初始化值且只能被赋值一次。* 比如:* final int MY_NUM;然后声明一个空参构造器,但是没有对MY_NUM赋值就会报错;* 3.3> final+static修饰的常量,相当于是类的常量。 可以直接通过"类名.常量"的方式直接调用。* 4、final修饰方法:方法不能再被重写* */
public class Demo1 {public static void main(String[] args) {System.out.println(D.MONDAY);}
}
package com.goshawk.finaldemo;/*** final练习二* */
public class Demo2 {final String name;{name = "小明";}public void method(){System.out.println(name);}public void method2(final String name){System.out.println(name);final int age;age = 10;System.out.println(age);}public static void main(String[] args) {Demo2 demo2 = new Demo2();demo2.method();demo2.method2("小赵");}
}
final
的总结final
修饰类:此类不能被继承。final
修饰方法:此方法不能被覆盖。final
修饰变量:此变量值不能被改变(无初始值、只允许赋值一次)。 似是而非的,像却又不是;具备某种对象的特征,但又不完整。
抽象类没有具体的代码实现,只是规定了方法的基本属性,然后由子类去实现具体的代码,抽象类主要是为了定义规则而存在的。
/**
Animal仅是一种会吃会睡的对象,再无其他行为,不够具体、不够完整。程序是用来模拟现实世界、解决现实问题的;
现实世界中存在的都是 动物 具体的子类对象,并不存在动物对象,所以,Animal不应该被独立创建成对象。
*/
public class TestAbstract{public static void main(String[] args){Animal a = new Animal();}
}class Animal{String breed;int age;String sex;public void Animal(){}public void eat(){System.out.println("动物在吃东西");}public void sleep(){System.out.println("动物在睡觉");}
}
abstract
修饰类,此类不能new对象。abstract
修饰的类,称为抽象类。new
对象。public class TestAbstract{public static void main(String[] args){// Animal a = new Animal(); 这里的Animal是抽象的,无法实例化。}
}abstract class Animal{String breed;int age;String sex;public void Animal(){}public void eat(){System.out.println("动物在吃东西");}public void sleep(){System.out.println("动物在睡觉");}
}
abstract
关键字修饰 abstract class 类名{}
abstract 返回值类型 方法名();
/**
使用抽象的经验:
抽象父类,可以作为子类的组成部分,依附于子类对象存在,由 父类共性+子类独有 组成完整的子类对象。
*/
public class TestAbstract{public static void main(String[] args){Animal a1 = new Dog();Animal a2 = new Cat();}
}abstract class Animal{public Animal(){}public void eat(){System.out.println("动物在吃东西")}public void sleep(){System.out.println("动物在睡觉")}
}class Dog extends Animal{}class Cat extends Animal{}
package com.goshawk.abstractdemo;public abstract class Person {public abstract void eat();}
package com.goshawk.abstractdemo;public class Teacher extends Person{@Overridepublic void eat() {System.out.println("在一个优雅的环境下吃饭");}
}
package com.goshawk.abstractdemo;public class Student extends Person{@Overridepublic void eat() {System.out.println("吃有营养的东西");}
}
package com.goshawk.abstractdemo;public class Worker extends Person{// 如果子类继承了Person(),就必须要重写这个抽象方法,或者本身也是一个抽象类@Overridepublic void eat() {}
}
package com.goshawk.abstractdemo;public abstract class Programmer extends Person{}
package com.goshawk.abstractdemo;public abstract class Animal {private String name;public void eat(){System.out.println("eat...");}public abstract void sleep();
}
package com.goshawk.abstractdemo;/*** 抽象类* 1、应用场景* 我们发现一个父类定义的功能,所有的子类都会去重写,那么父类的这个功能(方法)的内容就没有什么实际意义了。* 但是这个功能又必须有(内容没意义,但功能必须在)。* 于是就把父类中的这个方法定义成抽象方法。抽象方法没有方法体,由子类去做具体的实现。* 比如:* Worker类继承Person;* ----> 父类既定义了规则,又提升了开发的效率。*/
public class Demo1 {public static void main(String[] args) {Teacher t1 = new Teacher();t1.eat();Worker worker = new Worker();worker.eat();}
}
package com.goshawk.abstractdemo;/*** abstract(抽象的)* 1、抽象方法* 使用abstract关键字修饰的方法* 格式:* 权限修饰符 abstract 返回值类型 方法名(参数列表);* # 注意:抽象方法没有方法体** 2、抽象类* 有抽象方法的类称为抽象类。没有抽象方法的类也可以是抽象类。* 抽象类和抽象方法的具体逻辑:* 2.1> 抽象类不能被实例化(也就是不能创建类的对象)* 2.2> 有抽象方法所在的类一定是抽象类。* 2.3> 子类继承父类,如果子类要想被实例化,那么子类中的抽象方法必须全部被重写,否则子类也只能是抽象类。* 2.4> 抽象类可以没有任何抽象方法。*/
public class Demo2 {public static void main(String[] args) {}
}
package com.goshawk.abstractdemo;public abstract class A {public abstract void method1();
}
package com.goshawk.abstractdemo;public abstract class B extends A{public abstract void method2();
}
package com.goshawk.abstractdemo;public abstract class C extends A{public abstract void method3();
}
package com.goshawk.abstractdemo;public class D extends C{// 重写所有的抽象方法public void method1(){};public void method2(){};public void method3(){};
}
/**
需求:
Dog中的eat()应输出:狗在吃骨头
Cat中的eat()应输出:猫在吃鱼
*/
abstract class Animal{public void eat(){System.out.println("动物在吃东西");}public void sleep(){System.out.println("动物在睡觉");}}clas Dog extends Animal{}class Cat extends Animal{}
abstract
修饰的方法,称为抽象方法,只有方法声明,没有方法实现({}
的部分)。意为不完整的方法,必须包含在抽象类中。abstract class Animal{public abstract void eat();public void sleep(){System.out.println("动物在睡觉");}
}class Dog extends Animal{public void eat(){System.out.println("狗在吃骨头");}
}class Cat extends Animal{public void eat(){System.out.println("猫在吃鱼");}
}
abstract
修饰类:不能new
对象,但可以声明引用。abstract
修饰方法:只有方法声明,没有方法实现。(需包含在抽象类中)package com.goshawk.abs2;/*** 交通工具类*/
public abstract class Vehicle {private String brand;public Vehicle() {}public Vehicle(String brand) {super();this.brand = brand;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public abstract void run();}
package com.goshawk.abs2;public class Car extends Vehicle{public Car() {}public Car(String brand) {super(brand);}@Overridepublic void run() {System.out.println(super.getBrand()+"牌的汽车正在前进");}
}
package com.goshawk.abs2;public class Bike extends Vehicle{public Bike() {}public Bike(String brand) {super(brand);}@Overridepublic void run() {System.out.println(super.getBrand()+"牌的自行车正在前进");}
}
package com.goshawk.abs2;public class Master {private String name;public Master() {}public Master(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void goHome(Vehicle vehicle){System.out.println(this.name+"下班回家了");vehicle.run();}
}
package com.goshawk.abs2;public class TestMaster {public static void main(String[] args) {Master xiaoming = new Master("小明");Vehicle car = new Car("奔驰");xiaoming.goHome(car);Vehicle yongjiu = new Bike("永久");xiaoming.goHome(yongjiu);}
}
package com.goshawk.abstractdemo;/*** 抽象的练习* 汽车工厂已经将车的主体完成,汽车已经可以开动了,* 后期需要根据不同的用途安装不同的部件,* 货车需要安装货箱,用来拉货,客车需要安装座椅,用来拉人。*/
public class Demo3 {
}abstract class Car{/*** 安装部件*/public abstract void setParts();
}class Truck extends Car{/*** 货车*/@Overridepublic void setParts() {System.out.println("安装货箱");}
}class PassengerCar extends Car{/*** 客车*/@Overridepublic void setParts() {System.out.println("安装座椅");}
}
接口其实就是抽象类的升级版,接口里面都是抽象方法。
从狭义上来讲,接口就是指java
中的interface
。
从广义上来讲,就是对外提供规则的都是接口。
微观概念:接口是一种能力。
宏观概念:接口是一种标准(标准的规范)。
经验:Java
为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。
接口支持多实现,可为类扩充多种能力。
package com.goshawk.interfacedemo;interface MyInterface{// 公开的静态常量public static final String FIELD = "value";String NAME = "接口"; // 不显示加 public static final 则默认// 公开的抽象方法public abstract void method();void method2(); // 不显示加public abstract 则默认公开的抽象方法
}
package com.goshawk.interfacedemo;public class TestMyInterface {public static void main(String[] args) {MyInterface myInterface; // 使用接口创建一个变量}
}
interface
关键字定义接口package com.goshawk.interfacedemo;interface MyInterface{// 公开的静态常量public static final String FIELD = "value";String NAME = "接口"; // 不显示加 public static final 则默认// 公开的抽象方法// public abstract void method();void method2(); // 不显示加public abstract 则默认公开的抽象方法
}
package com.goshawk.interfacedemo;public class Impl implements MyInterface{/*** 类实现接口*/@Overridepublic void method2() {System.out.println("method");}
}
package com.goshawk.interfacedemo;public class TestMyInterface {public static void main(String[] args) {MyInterface myInterface = new Impl();myInterface.method2();}
}
interface
表示 interface 接口名{}
abstract
关键字可以省略implements
表示 class 类名 implements 接口名{}
Object
类中所定义的方法public static final
修饰。public abstract
修饰。接口允许多实现,一个类可以具备多个能力,同时实现多个父接口,若实现多个父接口,子类(普通类),必须覆写所有的抽象方法。
package com.goshawk.interface_1;
/*** 飞行能力*/
public interface Flyable {void fly();
}
package com.goshawk.interface_1;/*** 喷火能力*/
public interface Fireable {void fire();
}
package com.goshawk.interface_1;/*** 接口支持多实现,可为类扩充多种能力*/
public class Person implements Flyable, Fireable{String name;int age;public Person(){}public Person(String name, int age) {this.name = name;this.age = age;}public void eat(){System.out.println("吃东西");}public void sleep(){System.out.println("睡觉");}@Overridepublic void fly() {System.out.println(name + "开始飞");}@Overridepublic void fire() {System.out.println(name + "开始喷火");}
}
package com.goshawk.interface_1;public class TestPerson {public static void main(String[] args) {Person xiaoming = new Person("小明", 20);xiaoming.fly();System.out.println("_________多态_________");Flyable flyable = new Person("小赵", 21);flyable.fly();Fireable fireable = new Person();fireable.fire();}
}
USB接口表示一种规范,鼠标、风扇、U盘等等这些外接设备都属于USB接口的子类,我们在日常生活中使用电脑的时候,我们并不关心到底哪个具体设备插入了我们的电脑,只要这个设备满足了USB接口,就都能被电脑识别并使用。就是说,一个接口,可以接受无数种设备,只要这个设备满足USB接口,都可以插入电脑并被电脑识别。兼容所有的USB子类对象。
package com.goshawk.interface_4;public interface Usb {void service();
}
package com.goshawk.interface_4;public class Upan implements Usb{@Overridepublic void service() {System.out.println("U盘连接成功,开始工作");}
}
package com.goshawk.interface_4;public class Fan implements Usb{@Overridepublic void service() {System.out.println("风扇连接电脑成功,开始工作");}
}
package com.goshawk.interface_4;public class Mouse implements Usb{@Overridepublic void service() {System.out.println("鼠标连接成功,开始工作");}
}
package com.goshawk.interface_4;public class Computer {Usb usb1;Usb usb2;Usb usb3;public void run(){System.out.println("电脑开始工作");if (usb1!=null){usb1.service();}if (usb2!=null){usb2.service();}if (usb3!=null){usb3.service();}}
}
package com.goshawk.interface_4;public class TestComputer {public static void main(String[] args) {Computer lenovo = new Computer();Usb mouse = new Mouse();Usb fan = new Fan();Usb upan = new Upan();// 把usb连接到电脑上lenovo.usb1 = mouse;lenovo.usb2 = fan;lenovo.usb3 = upan;lenovo.run();}
}
public
。Object
中的公开方法(特殊)。package com.goshawk.interface_2;public abstract class Animal {// 父类方法public void eat(){System.out.println("吃");}// 父类方法public void sleep(){System.out.println("睡觉");}
}
package com.goshawk.interface_2;public interface Runnable {void run();
}
package com.goshawk.interface_2;public interface Swimmable {void swim();
}
package com.goshawk.interface_2;/*** 注意:继承在前面,实现在后面*/
public class Dog extends Animal implements Runnable, Swimmable{// 独有方法public void shout(){System.out.println("狗开始叫");}// 接口方法@Overridepublic void run() {System.out.println("狗在跑");}// 接口方法@Overridepublic void swim() {System.out.println("狗在游泳");}
}
package com.goshawk.interface_2;public class TestDog {public static void main(String[] args) {/**多种不同类型的引用指向同一个对象时,表示看待对象的视角不同Dog dog:将狗当狗看Animal a:将狗当动物看Runnable r:将狗当会跑的东西看Swimmable s:将狗当会游的东西看不同引用所能看到的对象范围不同,只能调用自身类型中所声明的部分。*/Dog dog = new Dog();Animal a = dog;Runnable r = dog;Swimmable s = dog;}
}
类与类:
extends 父类名称
类与接口:
implements 接口名称1, 接口名称2, 接口名称n
接口与接口:
extends 父类接口1, 父类接口2, 父类接口n
package com.goshawk.interface_2;import java.io.Serializable;public interface Runnable extends Swimmable, Serializable, Cloneable {void run();
}
package com.goshawk.interface_3;/*** 常量接口*/
public interface ConstInterface {String CONST1 = "aaa";String CONST2 = "bbb";String CONST3 = "ccc";
}
package com.goshawk.interface_3;public class TestConstInterface {public static void main(String[] args) {if (ConstInterface.CONST1.equals("aaa")){System.out.println("COUNT1");}}
}
Serializable
(可序列化)Cloneable
(可克隆的)package com.goshawk.interfacedemo;//public abstract class Person {
// public abstract void eat();
// public abstract void sleep();
// public abstract void walk();
//}
// ---->
// 定义一个规则
public interface Person {// 等同于 public static final String MALE = "男性";String MALE = "男性";String FEMALE = "女性";// 等同于 public abstract void eat();void eat();void sleep();void walk();
}
package com.goshawk.interfacedemo;public class Teacher implements Person{@Overridepublic void eat() {}@Overridepublic void sleep() {}@Overridepublic void walk() {}
}
package com.goshawk.interfacedemo;/*** 接口:* 1、定义* 接口是一个极端的抽象类,因为接口中只有抽象方法和全局常量(静态的常量)。* 抽象类Person的eat方法是一个抽象方法,定义的是一种规则,如果一个类中全部都只是规则,没有其他的普通的属性、普通的方法等,* 那么这个类就可以直接用接口来描述。** 2、接口使用的格式* 类的class改用interface即可。** 3、接口中的内容* 3.1> 抽象方法:方法前默认使用public abstract* 3.2> 全局静态常量:属性前默认使用public static final修饰***/
public class Demo1 {public static void main(String[] args) {System.out.println(Person.MALE);}
}interface A{}
package com.goshawk.interfacedemo;public interface Animal {String show();
}
package com.goshawk.interfacedemo;// implements ==> 实现某一种功能/规则
public class Cat implements Animal{@Overridepublic String show() {return null;}
}
package com.goshawk.interfacedemo;/*** 接口的使用* implements 一个类去实现一个接口* 如果一个类没有重写接口的所有抽象方法,该类必须是抽象类。** public class Cat implements Animal***/
public class Demo2 {
}
Java
为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。public
。