java面向对象三大特性、抽象类和接口、内部类及OOP实战--(基于狂神说)

目录

一 面向对象三大特性

1 封装

2 继承

3 多态

二 抽象类和接口

(1)抽象类:

(2)接口

三 内部类


一 面向对象三大特性

        三大特性:封装、继承、多态

1 封装

        定义:在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

        程序追求 高内聚、低耦合;

        封装(数据的隐藏)通常,应禁止直接访问一个对象中数据的实际表示,而通过操作接口来访问,这称为信息隐藏。

        属性私有,get/set方法进行调用或赋值

简单例题:

package OOP.Encapsulation_fengzhuang;

//类  private:私有
public class Student {
    //属性私有

    private String name;//名字
    private int id;//学号
    private char sex;//性别

    //get和set方法,实现外部可以调用或赋值
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //使用alt+insert 可以快速生成get/set方法

}
package OOP.Encapsulation_fengzhuang;

public class Demo01 {
    public static void main(String[] args) {
        //实例化一个Student类
        Student s1 = new Student();
        // s1.name();  //这种方法的错误的,因为name是私有的
        //通过get/set方法对私有属性进行调用或赋值
        s1.getName();
        System.out.println("实例化的对象S1的name值:" +s1.getName());
        s1.setName("yuan");
        System.out.println("set后对象S1的name值:" +s1.getName());
    }
}

        通过封装,可以在外界调用set时,对输入参数进行合法性判断。

/通过封装,可以在调用set方法时对输入值进行合法性判断
    public void setAge(int age) {
        if(age >100 || age<0){
            System.out.println("年龄输入不合法");
        }else{
            this.age = age;
        }
    }
        s1.setAge(123);//会被set的合法性判断拦截,输出值仍为默认值
        System.out.println(s1.getAge());

        封装的好处:1 提高程序的安全性,保护数据

                2 隐藏代码的实现细节

                3 统一接口

                4 系统可维护增加

2 继承

        (1)定义:关键字 extands;继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为

        java中只有单继承,没有多继承。

        继承是类与类之间的一种关系。除此之外,还有依赖、组合、聚合等关系;

        继承关系的两个类,一个为父类(基类),一个为子类(派生类),子类继承父类。

        子类和父类之间,从意义上讲应该具有”is a“的关系。即dog是一种动物;

快捷键:ctrl+H  查看子类父类继承树

例题:Person为父类,有一个say方法;Student为子类,继承Person

package OOP.extands_jicheng;
//父类
//在java中,所有的类,都默认直接或间接继承object类
public class Person {
    String name;
    public void say(){
        System.out.println("会说话");
    }
}
package OOP.extands_jicheng;
//学生,学生 is a person;继承person类
public class Student extends Person{
    //子类继承了父类,会拥有父类的全部方法;
    //创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
    //但私有的private 不能被继承
}

main类:

package OOP.extands_jicheng;

public class Demo01 {
    public static void main(String[] args) {
        //因为Student继承了person类,所以虽然student中没有定义say方法,但也可以用
        Student S2 = new Student();
        S2.say();
    }
}

        (2) object类

              在java中,所有的类,都默认直接或间接继承object类

        (3)super

                super注意点:

                        1 super调用父类的构造方法,必须在构造方法的第一个

                        2 super必须只能出现在子类的方法或者构造方法中

                        3 super和this不能同时调用构造方法

                和this的区别

                        代表的对象不同:this 本身调用者这个对象;super 代表父类对象的应用

                        前提不同:this 没有继承也可以使用;super 只能在继承条件下才能使用

                        构造方法:this() 本类的构造;   super() 父类的构造

                例题:

父类:

package OOP.extands_jicheng;

//父类
//在java中,所有的类,都默认直接或间接继承object类
public class Person {
    //    String name;
    public void say() {
        System.out.println("会说话");
    }

    //super的例子
    //1 属性值的测试
    protected String name = "kuangshen";

    //2 方法的测试
    public void print() {
        System.out.println("person");
    }
    //3 构造器


    public Person() {
        System.out.println("Person无参执行了");
    }

    public Person(String name) {
        this.name = name;
    }
}

子类:

package OOP.extands_jicheng;

import com.sun.org.apache.xerces.internal.impl.xpath.XPath;

//学生,学生 is a person;继承person类
public class Student extends Person {
    //子类继承了父类,会拥有父类的全部方法;
    //创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
    //但私有的private 不能被继承

    //super例子
    //1 属性值的测试
    private String name = "qinjiang";

    public void test(String name) {
        System.out.println(name);//输出传入参数
        System.out.println(this.name);//输出子类定义的私有属性值
        System.out.println(super.name);//输出父类的属性值
    }

    //2 方法的测试
    public void print() {
        System.out.println("student");
    }

    public void test2() {
        print(); //先输出student类的print方法
        this.print();//输出student类的print方法
        super.print();//输出person类的print方法
    }
    //3 构造器

    //输出结果显示,子类默认首先调用了父类的无参构造,之后执行自己的
    public Student() {
        //此处隐藏了父类的无参构造
        //可以显示,但必须是第一行
        super();//调用无参构造
//        super("name");//可以不写
        System.out.println("Student无参执行了");
    }
    //如果父类使用了有参构造,必须显式写出无参构造,否则子类调用父类无参构造会报错;但直接调用有参构造可以使用
}

main类:

package OOP.extands_jicheng;

import com.sun.org.apache.xerces.internal.impl.xpath.XPath;

//学生,学生 is a person;继承person类
public class Student extends Person {
    //子类继承了父类,会拥有父类的全部方法;
    //创建一个student对象时,虽然在此处什么也没定义,但父类的公有方法 public都可以用
    //但私有的private 不能被继承

    //super例子
    //1 属性值的测试
    private String name = "qinjiang";

    public void test(String name) {
        System.out.println(name);//输出传入参数
        System.out.println(this.name);//输出子类定义的私有属性值
        System.out.println(super.name);//输出父类的属性值
    }

    //2 方法的测试
    public void print() {
        System.out.println("student");
    }

    public void test2() {
        print(); //先输出student类的print方法
        this.print();//输出student类的print方法
        super.print();//输出person类的print方法
    }
    //3 构造器

    //输出结果显示,子类默认首先调用了父类的无参构造,之后执行自己的
    public Student() {
        //此处隐藏了父类的无参构造
        //可以显示,但必须是第一行
        super();//调用无参构造
//        super("name");//可以不写
        System.out.println("Student无参执行了");
    }
    //如果父类使用了有参构造,必须显式写出无参构造,否则子类调用父类无参构造会报错;但直接调用有参构造可以使用
}

        (4)方法重写

                前提:需要有继承关系,子类重写父类的方法

                1 方法名必须相同;

                2 参数列表必须相同;

                3 修饰符:范围可以扩大但不能缩小 :public > Protected>Default>private

                4 抛出的异常:范围,可以被缩小,但不能扩大; ClassNotFoundException--->Exception(大)

                重写,子类的方法和父类必须一致;方法体不同

                为什么重写:1 父类的功能,子类不一定需要或者不一定满足;

                快捷键:alt + Insert   : override

例题:

        父类:

package OOP.extands_jicheng;

//B是父类
public class B {
    //    //父类定义的方法test
    public static void test() {
        System.out.println("B=>test()");
    }

    //父类定义的方法test2
    public void test2() {
        System.out.println("B=>test2");
    }


}

子类:

package OOP.extands_jicheng;

//A继承于B,A是子类
public class A extends B {
    //    //A 自定义test方法
    public static void test() {
        System.out.println("A=>test()");
    }

    //重写父类的方法 Override
    @Override //注解:有功能的注释
    public void test2() {
        System.out.println("A=>test2()");
    }
}

主类:

package OOP.extands_jicheng;

public class Demo02 {
    public static void main(String[] args) {

        //方法的调用只和左边有关
        A a = new A();
        a.test(); //输出为A定义的方法

        //父类的引用指向子类是允许的
        B b = new A();
        b.test(); //输出是B定义的方法

        //重写方法测试,非静态方法,子类重写了父类的方法
        //输出都是子类的方法输出
        a.test2();
        b.test2();

    }

3 多态

        定义:多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。

        课程中的定义:即同一方法可以根据发送对象的不通过而采用不同的行为方式。

        一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多。

多态存在的条件:1 有继承关系

                                2 子类重写父类的方法

                                3 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态;

另外:static 方法,属于类,它不属于实例; private 方法, finnal  常量这三种是没有多态的。

例题:

        父类:

package OOP.polymorphism_duotai;
//父类
public class Person {

    public void run(){
        System.out.println("父类的run");
    }
    public void study(){
        System.out.println("person");
    }
}

子类:

package OOP.polymorphism_duotai;
//子类
public class Student extends Person{

    public void eat(){
        System.out.println("子类的son");
    }

    @Override
    public void study() {
        System.out.println("子类重写的方法");
    }
}

主类:

package OOP.polymorphism_duotai;

public class Demo01 {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的
//        new Student();
//        new Person();
        //可以指向的引用类型就不确定了
        Student s1 = new Student();
        Person s2 = new Student();
        Object s3 = new Student();

        s2.run();//可以调用父类的方法
        s1.run();//可以调用父类的方法
        System.out.println("---------------");
        s1.eat();//只能子类可以调用自己独有的方法
        //s2.eat(); //父类调用会报错
        ((Student) s2).eat();//强制转换成子类类型后可以调用
        System.out.println("---------------");
        s1.study();//子类重写方法后,输出是子类重写后的方法
        s2.study();//子类重写方法后,输出是子类重写后的方法
    }
}

        instanceof (类型转换) 引用类型,判断一个对象是什么类型;

                范围大小顺序:Object >person=String > student = teacher

例题:A :person   B: student  C teacher

package OOP.polymorphism_duotai;

public class Demo02 {
    public static void main(String[] args) {

        //范围大小顺序  Object > A = String > B = C
        Object a = new B();
        //System.out.println(X instanceof Y); //能不能编译通过
        //如果左边是右边的子类,则为true
        System.out.println(a instanceof Object);//true
        System.out.println(a instanceof A);//true
        System.out.println(a instanceof B);//true
        System.out.println(a instanceof C);//false,和B同属于A的子类
        System.out.println(a instanceof String);//false
        System.out.println("--------------");
        A b = new B();
        System.out.println(b instanceof Object);//true
        System.out.println(b instanceof A);//true
        System.out.println(b instanceof B);//true
        System.out.println(b instanceof C);//false
        //System.out.println(b instanceof String); //flase 会编译报错
        System.out.println("---------------");
        B c = new B();
        System.out.println(c instanceof Object);//true
        System.out.println(c instanceof A);//true
        System.out.println(c instanceof B);//true
        //System.out.println(c instanceof C);//true //FALSE 会编译错误
    }
}

类型转换:

        子类转换为父类,向上转型,可能会丢失掉自己独有的子类方法

        父类转换为子类,向下转型,需要强制转换,丢失精度,但会获得子类的独有的方法

public class Demo02 {
    public static void main(String[] args) {

        A obj = new B(); //A 是父类,B是子类
        //可以将这个对象转换为子类的类型,然后使用子类的方法
        ((B) obj).go(); //把父类转换为子类,强制转换
        B obj2 = new B();
        //子类转换为父类,向上转型
        //作用是方便方法的调用,减少重复的代码
    

Static 关键字详解

        修饰属性时称为静态属性;修饰方法时称为静态方法。修饰代码块时称为静态代码块。

package OOP.polymorphism_duotai;

//static详解
public class static_1 {
    private static int age; //静态变量
    private double score; //非静态变量

    //非静态方法
    public void run() {
        System.out.println("run");
    }

    //静态方法
    public static void go() {
        System.out.println("go");
    }

    //匿名静态代码块,创建类的时候就会被执行,会第二个被执行,可以用来赋初始值
    { //代码块
        System.out.println("匿名代码块");
    }      //匿名代码块

    //静态代码块,创建类的时候就会被执行,会首先被执行,且只被执行一次
    static {
        //代码块
        System.out.println("静态代码块");
    }

    public static void main(String[] args) {
        static_1 student = new static_1();
        //静态属性,与非静态属性
        System.out.println(static_1.age);//静态变量可以直接引用
        //System.out.println(static_1.score); //非静态变量不可以直接引用

        System.out.println(student.age);//静态变量可以直接引用
        System.out.println(student.score);//非静态变量可以直接引用
        //静态方法,非静态方法
        // run(); //非静态方法直接调用不可以
        go();//静态方法直接调用就可以
        student.run();//实例化后可以直接调用
        student.go();//实例化后也可以直接调用
        //静态代码块,创建类的时候就会被执行

    }
}

二 抽象类和接口

       (1)抽象类:

         abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

        1 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

        2 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

        3 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

        4 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

        5 抽象类存在的意义:提升开发效率

抽象类:

package OOP.Abstract;
//抽象类 abstract
public  abstract class Action {
    //抽象方法:1 只有名字,没有实现;2 抽象类必须在抽象方法中
    //3 不能new, 只能靠子类来实现
    public abstract  void fun();
    //普通方法,抽象类中可以写普通方法
    public void doSomething(){
    }
}

继承抽象类的子类:

package OOP.Abstract;

public class A extends Action{
    @Override
    public void fun() {
        System.out.println("重写的抽象方法");
    }
}

(2)接口

        接口:只有约束,没有实现;也就是说只有抽象方法。

        定义:接口就是规范,定义的是一组规则。接口的本质是契约。OO的精髓,是对对象的抽象,而最能体现这一点的就是接口。

        关键字:声明接口的关键字是interface。

        三者的区别:普通类---只有具体实现; 抽象类---具体实现和规范(抽象方法)都有;接口---只有规范(抽象方法)。

例子:

接口:

package OOP.Interface;
//interface 定义接口的关键字
public interface UserService {
    //接口中所有的定义都是抽象的 相当于隐藏了public abstract
    public abstract void add(String name);//默认是前面有public abstract
    void del(String name);
    void update(String name);
    void query(String name);
    //在接口中定义属性时,其实时定义常量
    public static final int AGE = 99;
}

实现接口的类:(可以多继承,继承多个接口)

package OOP.Interface;
//继承接口,重写接口的方法
public class UserServiceImpl implements UserService{
    @Override
    public void add(String name) {
    }
    @Override
    public void del(String name) {
    }
    @Override
    public void update(String name) {
    }
    @Override
    public void query(String name) {
    }
}

接口的作用:

        1 约束

        2 定义一些方法,让不同的人实现

        3 方法都是public abstract 可以直接调用

        4 接口中的属性都是 public static fina 常数,可以直接使用

        5 接口不能被实例化,接口中没有构造方法

        6 implements可以实现多个接口

        7 必须要重写接口中的方法。

三 内部类

        内部类就是在一个类的内部再定义一个类,例如,A类中定义一个B类,那么B类相对于A类来说就是内部类,而A就是B的外部类。

        1 成员内部类

        2 静态内部类

        3 局部内部类

        4 匿名内部类

package OOP.inclass;

public class Outer {
    private int id = 10;

    public void out() {
        System.out.println("这是外部类的方法");
    }

    // 在外部类的方法中写入类,叫局部内部类
    public void out_2() {
        class Inner_3 {
            public void in_3() {
                System.out.println("局部内部类");
            }
        }
    }


    //成员内部类
    public class Inner {
        public void in() {
            System.out.println("这是内部类的方法");
        }

        //用途之一,可以获得外部类的私有属性
        public void getID() {
            System.out.println(id);
        }
    }

    //静态内部类:带static的内部类
    public static class Inner_2 {
        public void in() {
            System.out.println("这是静态内部类");
        }
    }

    //匿名类,直接new,但没有起名字
    // new A().in_4;  在main方法中可以用。

}

//一个class只能有一个public类,可以有多个非public的类
class A {
    public void in_4() {
        System.out.println("这也是一个内部类");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值