JavaDay3
JavaDay3
面向对象
把大象装进冰箱:
1、Java语言通过一个类来描述生活中的事物
2、有哪些类?
如上:大象类、冰箱类、冰箱装大象组合类。
3、类中有什么?
属性和行为
4、类与类的关系是什么?
继承关系
面向对象开发:
创建对象、使用对象、指挥对象
特征:封装、继承、多态
一个Java文件中可以写多个类,但只有一个类能被public修饰,且这个类和Java文件名保持一致。
当看到一个类作为方法的参数类型时,将来调用时需要传入该类或者该类的子类的对象。
1、方法中的变量使用顺序遵循就近原则
2、Java中提供了个关键字this,使用this关键字,可以在方法中使用当前对象里其它成员
使用 this.变量名 不考虑就近原则
构造方法
创建对象时所调用的方法
特点:方法名和类名保持一致,无返回值,无void
注意:1、若未自行去写构造方法,默认JVM会提供一个无参无方法体的构造方法
2、若写了,无论无参或有参,则JVM将不会再提供构造方法
3、构造方法也是方法,也可以发生重载。
4、可利用构造方法可以传参的特性,对参数进行赋值。
关键字static
/*
java中提供了一个关键字:static 可以表示一个类多个对象共享一个成员
可以修饰成员变量和成员方法
注意事项:
1、被static修饰的成员称之为类成员,静态成员,不被任何一个对象私自拥有
2、类成员是可以直接通过类名的方式进行访问获取,优先于对象而存在的
3、非静态的成员方法既可以访问非静态的成员,也可以访问静态的成员
4、静态的成员方法只能访问静态的成员
*/
继承extends
package shujia.day05;
/*
java提供了一个关键字表示继承, extends
class 子类 extends 父类{
}
class A extends B{
}
A:子类,派生类
B:父类,超类,基类
*/
class Person2{
String name;
int age;
public void eat(){
System.out.println("吃饭");
}
public void study(){
System.out.println("学习");
}
}
class Student2 extends Person2{
// String name;
// int age;
//
// public void eat(){
// System.out.println("吃饭");
// }
//
// public void study(){
// System.out.println("学习");
// }
}
class Teacher2 extends Person2{
}
public class PersonDemo2 {
public static void main(String[] args) {
Student2 student2 = new Student2();
student2.name = "张三";
student2.age = 18;
System.out.println(student2.name+"--"+student2.age);
student2.eat();
student2.study();
}
}
package shujia.day05;
/*
使用继承的注意事项:
1、不要有一点相同的部分就使用继承
class A{
fun1();
fun2();
fun3();
}
class B{
fun2();
fun5();
fun6();
}
什么时候使用继承呢?两个类之间满足英语语法上的is a关系就可以了。
2、子类无法继承父类中的私有成员【私有的成员变量或私有的成员方法】
3、构造方法无法继承
4、子类继承父类之后,子类中可以编写自己特有的功能和属性
5、一个类同一时刻只能继承一个类,不允许一次继承多个类,但是可以多重继承,形成继承体系
*/
class Fu {
int a = 10;
static int b = 20;
private int c = 30;
// Fu(){
//
// }
public void show1(){
System.out.println("这是父类中的成员方法show1");
}
public static void show2(){
System.out.println("这是父类中的成员方法show2");
}
private void show3(){
System.out.println("这是父亲私有的成员方法show3");
}
}
class Zi extends Fu {
//int a = 10;
//static int b = 20;
int d = 100;
// public void show1(){
// System.out.println("这是父类中的成员方法show1");
// }
//
// public static void show2(){
// System.out.println("这是父类中的成员方法show2");
// }
// Fu(){
//
// }
public void fun1() {
System.out.println(a);
System.out.println(b);
show1();
show2();
// show3();
// System.out.println(c);
}
}
public class ExtendsDemo1 {
public static void main(String[] args) {
Zi zi = new Zi();
zi.fun1();
// zi.show1();
// Zi.show2();
}
}
//不允许继承多个类
package shujia.day05;
/*
继承和成员变量的关系:【就近原则】
先在方法内部->当前类的成员变量位置->父亲的成员变量
java提供了一关键字super可以在子类中使用直接父类中的非私有的成员【成员变量,构造方法,成员方法】
面试题:super和this的区别?
*/
class GrandFu3{
int b = 100;
}
class Fu3 extends GrandFu3{
//int b = 100;
int a = 10;
}
class Zi3 extends Fu3 {
//int b = 100;
int a = 20;
public void fun1() {
int a = 30;
int b = 200;
System.out.println(a);
System.out.println(this.a);
System.out.println(super.a);
// System.out.println(super.super.b); //无法使用super获取到间接父类中的成员
System.out.println(b);
GrandFu3 grandFu3 = new GrandFu3();
System.out.println(grandFu3.b);
}
}
public class ExtendsDemo3 {
public static void main(String[] args) {
Zi3 zi3 = new Zi3();
zi3.fun1();
}
}
package shujia.day05;
/*
继承和构造方法的关系:
1、子类的构造方法第一句默认会有一个super(), 调用的是父亲中的无参构造方法
2、要想初始化子类,必须先初始化其父类
3、无论子类构造方法第一句话调用的是父类中有参构造方法还是无参构造方法,都是对父亲的初始化
4、java中的类不允许多次初始化
5、子类构造方法中对父亲初始化的代码必须是第一句话
*/
class Fu4 {
// Fu4(){
// System.out.println("这是父亲中的构造方法。。。");
// }
Fu4(String n) {
System.out.println("这是父亲中的有参构造方法。。。" + n);
}
}
class Zi4 extends Fu4 {
Zi4() {
//super(); // 调用的是父亲中的无参构造方法
super("hello");
System.out.println("这是子类中的构造方法,,,");
// super("hello");
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
}
}
package shujia.day05;
/*
继承和成员方法的关系:
方法的重写:在继承关系中,子类中的方法声明【返回值类型,方法名,参数列表】与父类中的一模一样,只是方法实现不一样,这个现象成为方法的重写
方法的重载:在同一个类中,方法名一样,参数列表不同现象,方法的重载,与返回值无关。
面试题:方法的重载和重写什么区别?
注意:并不是所有的方法子类都能重写?
1、父类中静态的方法子类无法重写。可以继承使用父亲的静态成员,不能重写。
2、父类中的私有方法子类无法重写,私有的都无法继承,更不用想重写了。
3、重写和权限有关系吗? public protected 默认的 private
子类重写的方法权限不能比父亲的还要低 可以是大于等于,推荐除特殊要求外,保持一致
*/
class Fu6{
protected void fun1(){
System.out.println("这是父类中的fun1方法");
}
public static void fun2(){
System.out.println("这是父类中的静态的fun2方法");
}
private void fun3(){
System.out.println("这是父类中的私有的fun3方法");
}
}
class Zi6 extends Fu6{
// public void fun1(){
// System.out.println("这是父类中的fun1方法");
// }
@Override
protected void fun1(){
System.out.println("好好学习,天天向上!");
}
//无法重写
// public static void fun2(){
// System.out.println("数加666");
// }
//
// @Override
// private void fun3(){
// System.out.println("数加666");
// }
public void show1(){
fun1();
}
public int show1(String n){
return 10;
}
}
public class ExtendsDemo5 {
public static void main(String[] args) {
Zi6 zi6 = new Zi6();
zi6.show1();
zi6.fun1();
}
}
关键字final
package shujia.day05;
/*
子类可以重写父类中非私有,非静态的方法
新需求:只允许子类使用父类中的非私有,非静态的方法,不允许重写,一旦重写就会报错
java提供了一个关键字给我们使用final
final: 最终的,不可改变的
可以修饰类,变量,成员方法
修饰成员方法:方法不能被重写,可以被继承使用
修饰成员类:被final所修饰的类,类不能被继承
修饰变量:被final所修饰的变量,变量变常量,不能修改变量的值。
final修饰的变量赋值的时机:必须在构造方法完毕之前赋值,否则程序报错。
*/
//final class F{
//
//}
//
//class Z1 extends F{
//
//}
class Fu7{
public final void show(){
System.out.println("这是父类中的非私有,非静态的方法show");
}
}
class Zi7 extends Fu7{
final int A = 11;
public void fun1(){
// A = 12;
System.out.println(A);
}
// @Override
// public void show(){
// System.out.println("已重写父亲的方法show");
// }
}
class Demo2{
int a = 10;
}
class Demo3{
final int a;
//使用构造代码块给final修饰的变量赋值,优先于构造方法执行
// {
// a =100;
// }
//可以在构造方法执行过程中进行赋值
Demo3(){
a = 200;
}
}
public class ExtendsDemo6 {
public static void main(String[] args) {
// Zi7 zi7 = new Zi7();
// zi7.show();
// zi7.fun1();
// Math.PI
// final Demo2 d1 = new Demo2(); // 修饰引用数据类型变量,指的是地址值不能被修改
// System.out.println(d1.a);
// d1.a = 100;
// System.out.println(d1.a);
// d1 = new Demo2();
}
}
多态
package shujia.day06;
/*
多态:某一个事物,在不同时刻下的不同状态
实现多态有3个前提:
1、必须要有继承关系
2、要有方法的实现
3、要有父类的引用指向子类对象
水:气态的水,固态的水,液态的水
水果:苹果,香蕉,哈密瓜
动物:狗,猫
*/
class Animal{
String name;
int age;
Animal(){
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
class Dog extends Animal{
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat(){
System.out.println("🐕吃🥩");
}
@Override
public void sleep(){
System.out.println("🐕侧着睡");
}
}
class Demo1{
}
public class DuoTaiDemo1 {
public static void main(String[] args) {
//要有父类的引用指向子类对象
Animal a1 = new Dog(); //多态 //必须要存在继承关系,或者待会要说的实现关系
// Dog d1 = new Dog();
// Demo1 a2 = new Dog();
}
}
package shujia.day06;
/*
多态访问成员的特点:
1、成员变量: 编译看左,运行看左
2、成员方法: 编译看左,运行看右
3、静态成员方法: 编译看左,运行看左
*/
class Fu1{
int a = 10;
public void fun1(){
System.out.println("这是父类中的fun1方法");
}
public static void show1(){
System.out.println("这是父类中的静态成员方法show1");
}
}
class Zi1 extends Fu1{
int a = 20;
// @Override
// public void fun1(){
// System.out.println("这是子类中的fun1方法");
// }
public void fun1(){
System.out.println("这是子类中的fun1方法");
}
public static void show1(){
System.out.println("这是子类中的静态成员方法show1");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu1 f1 = new Zi1();
// System.out.println(f1.a); // 10
// f1.fun1();
f1.show1();
}
}
package shujia.day06;
/*
多态的好处
提高了程序的维护性(由继承保证)
提高了程序的扩展性(由多态保证)
*/
class Animal2 {
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
class Dog2 extends Animal2 {
@Override
public void eat() {
System.out.println("🐕吃🥩");
}
@Override
public void sleep() {
System.out.println("🐕侧着睡");
}
}
class Cat2 extends Animal2 {
@Override
public void eat() {
System.out.println("🐱吃🐟");
}
@Override
public void sleep() {
System.out.println("🐱蜷着睡");
}
}
class Pig extends Animal2 {
@Override
public void eat() {
System.out.println("🐖吃米");
}
@Override
public void sleep() {
System.out.println("🐖趴着睡");
}
}
class Tiger extends Animal2{
@Override
public void eat() {
System.out.println("🐅吃🐏");
}
@Override
public void sleep() {
System.out.println("🐅趴着睡");
}
}
class AnimalTool {
private AnimalTool() {
}
// 将来当你看到一个类作为方法的参数类型的时候,也可以传入该类的子类对象形成多态
public static void useAnimal(Animal2 animal2) { //Animal2 animal2 = new Tiger()
animal2.eat();
animal2.sleep();
}
// public static void useCat(Cat2 c){
// c.eat();
// c.sleep();
// }
//
// public static void useDog(Dog2 d){
// d.eat();
// d.sleep();
// }
//
// public static void usePig(Pig p){ //Pig p = new Pig()
// p.eat();
// p.sleep();
// }
}
public class DuoTaiDemo3 {
public static void main(String[] args) {
//我想养一只🐕
Dog2 d1 = new Dog2();
// d1.eat();
// d1.sleep();
// useDog(d1);
AnimalTool.useAnimal(d1); // new Dog2()
Dog2 d2 = new Dog2();
// d2.eat();
// d2.sleep();
// useDog(d2);
AnimalTool.useAnimal(d2);
//养🐱
Cat2 c1 = new Cat2();
// c1.eat();
// c1.sleep();
// useCat(c1);
AnimalTool.useAnimal(c1);
Cat2 c2 = new Cat2();
// c2.eat();
// c2.sleep();
// useCat(c2);
AnimalTool.useAnimal(c2);
//随着我养动物的种类越来越多,首先
//具体动物类必须定义,其次按照之前的写法,也会在当前类中写一个有关动物的使用方法
//我们可以单独使用一个类,将有关动物使用的功能方法放到一个类中,定义成工具类
Pig p1 = new Pig();
AnimalTool.useAnimal(p1); // new Pig()
//我们虽然可以实现新的动物,并且测试类中不会有新的方法添加
//但是工具类一般来说不会频繁的进行修改
//可以使用多态改进传参特点
Tiger tiger = new Tiger();
AnimalTool.useAnimal(tiger); // new Tiger()
}
}
package shujia.day06;
/*
使用多态的弊端:无法使用子类中特有的成员方法
*/
class Fu2{
}
class Zi2 extends Fu2{
public void show1(){
System.out.println("好好学习,天天向上!");
}
}
public class DuoTaiDemo4 {
public static void main(String[] args) {
// Zi2 zi2 = new Zi2();
// zi2.show1();
//向上转型
Fu2 f1 = new Zi2();
// f1.show1(); // 多态访问成员方法编译看左,父类中若没有该方法,就报错
//向下转型
Zi2 z1 = (Zi2)f1;
z1.show1();
}
}
/*
曹操和曹植的故事:
class 曹操{
fun1(){
带兵打仗
}
}
class 曹植 extends 曹操{
fun1(){
下棋
}
show(){
绘画
}
}
有一天,曹操带兵外出打仗,这时,邻国的敌人攻打过来了,需要战士们抵抗,但是战士只听从曹操的指挥
于是曹植想到一个办法,于是开始装爹。换上爹的衣服,粘上假胡子等等
曹操 c1 = new 曹植(); //向上转型
c1.fun1();
//c1.show();
当爹回来的时候,脱下爹的衣服,撕掉假胡子
曹植 c2 = (曹植)c1; // 向下转型
c1.fun1();
c1.show();
*/
抽象abstract
package shujia.day06;
/*
在此之前,我们写的动物类,水果类,人类等等,这些类在实际生活中其实就是一个概念的集合
而概念性的东西,在生活中是看不见摸不着的,这样的类,方法也不应该有具体的实现
java针对这种现实场景,提供了一个关键字:abstract用于表示抽象的概念
可以修饰类和方法
abstract关键字使用注意事项:
1、被abstract关键字修饰的类,称之为抽象类,抽象类无法实例化【不能创建对象】
2、抽象类可以借助具有的子类【没有被abstract关键字修饰的类】来创建对象
3、被abstract关键字修饰的方法,称之为抽象方法,抽象写法不能有大括号方法体
4、当一个具体的子类继承一个抽象类的话,必须要重写抽象父类中所有的抽象方法
5、抽象类中既可以存在具体实现的方法【有大括号的】,也可以存在抽象方法
6、当一个抽象类继承一个抽象类的话,可以选择性的重写方法,也可以都不重写
7、具体的类中不能存在抽象方法【有抽象方法的类一定是抽象类】
*/
//抽象类
abstract class Animal3{
// public void fun1(){
// System.out.println("好好学习,天天向上");
// }
// 抽象方法
public abstract void eat();
public abstract void sleep();
}
abstract class Demo2 extends Animal3{
}
class Dog3 extends Animal3{
// public abstract void show1();
@Override
public void eat() {
System.out.println("🐕吃🥩");
}
@Override
public void sleep() {
System.out.println("🐕侧着睡");
}
}
public class AbstractDemo1 {
public static void main(String[] args) {
// Animal3 animal3 = new Animal3();
Animal3 a1 = new Dog3(); // 抽象多态
// a1.fun1();
a1.eat();
a1.sleep();
}
}
package shujia.day06;
/*
抽象类中的成员特点:
成员变量:既可以存在变量,也可以存在常量
构造方法:抽象类是有构造方法,但是抽象类无法实例化,那么抽象类中的构造方法的意义是什么?
要想初始化子类,必须先初始化其父类
具体子类中构造方法的第一句话,默认是super()
成员方法:既可以是具体的实现方法,也可以是抽象方法
*/
abstract class Demo3{
int a= 10;
final int b = 20;
Demo3() {
}
}
class DemoZi extends Demo3{
DemoZi(){
//super()
}
}
public class AbstractDemo2 {
public static void main(String[] args) {
// Demo3 d = new Demo3();
}
}
/*
目前我们学过的关键字:
static:被static修饰的成员属于类成员,可以修饰变量,方法
final:修饰类,变量,方法
abstract:修饰类和方法
与abstract不合法的关键字组合:
abstract final
abstract static
private abstract
*/
扩展关键字interface
package shujia.day06;
/*
java为了描述现实生活中额外扩展功能的现象,提供了一个关键字给我们使用,interface
可以使用该关键字定义一个接口,接口中定义额外的方法【扩展功能】
接口其实可以被看作一个特殊类,也是会被JVM编译成一个class文件的
接口中成员的特点:
1、接口中不能有构造方法,自己写都不允许,接口不能实例化
2、接口中的方法只能是抽象方法
3、一个类要想实现一个接口的话,需要使用关键字implements
class A implements 接口1{
}
4、当一个具体的类实现一个接口的时候,必须实现接口中所有的抽象方法
*/
abstract class Animal4{
public abstract void eat();
public abstract void sleep();
}
class Dog4 extends Animal4{
@Override
public void eat() {
System.out.println("🐕吃🥩");
}
@Override
public void sleep() {
System.out.println("🐕侧着睡");
}
}
//定义一个接口
interface ByCycle{
// public void cycle(){
// System.out.println("骑车");
// }
public abstract void cycle();
}
class ByBikeDog extends Dog4 implements ByCycle{
@Override
public void cycle() {
System.out.println("狗会骑车!");
}
}
public class InterfaceDemo1 {
public static void main(String[] args) {
// ByCycle byCycle = new ByCycle();
//创建一个普通的小狗
Dog4 dog4 = new Dog4();
dog4.eat();
dog4.sleep();
// dog4.cycle();
System.out.println("-----------------------------");
//创建一个会骑车的小狗
ByBikeDog byBikeDog = new ByBikeDog();
byBikeDog.eat();
byBikeDog.sleep();
byBikeDog.cycle();
}
}
package shujia.day06;
/*
接口中成员的特点:
1、接口中不能有构造方法,自己写都不允许,接口不能实例化
2、接口中的方法只能是抽象方法
3、一个类要想实现一个接口的话,需要使用关键字implements
class A implements 接口1{
}
4、当一个具体的类实现一个接口的时候,必须实现接口中所有的抽象方法
5、接口中的方法默认会被public abstract关键字组合修饰,现在学习阶段写上,后面工作时不要写
6、接口中只能存在常量,不能有变量,默认会被public static final修饰
*/
interface Inter1{
int a = 10;
void fun1();
}
class Demo5 implements Inter1{
@Override
public void fun1() {
System.out.println("好好学习,天天向上!");
}
}
public class InterfaceDemo2 {
public static void main(String[] args) {
Demo5 demo5 = new Demo5();
demo5.fun1();
// demo5.a = 100;
System.out.println(demo5.a);
}
}
package shujia.day06;
/*
类与类,类与接口以及接口与接口的关系
类与类是继承关系,使用extends关键字进行连接,只能单继承,不能一次性继承多个,抽象类也符合这个规则
类与接口是实现关系,使用implements关键字连接,一个类可以一次同时实现多个接口,也可以继承一个类的同时实现接口
接口与接口是继承关系,使用extends关键字进行连接,可以多继承
面试题:java中允许多继承吗?
*/
interface Inter2{
void fun1();
void fun2();
}
interface Inter3{
void show1();
}
interface Inter4 extends Inter2,Inter3{
// void fun1();
// void fun2();
// void show1();
void show2();
}
//abstract class Demo6 implements Inter2{
// // public abstract void fun1();
// // public abstract void fun2();
//}
class Demo6 extends A implements Inter2,Inter3{
@Override
public void fun1() {
}
@Override
public void fun2() {
}
@Override
public void show1() {
}
}
public class InterfaceDemo3 {
public static void main(String[] args) {
}
}