javaoop-day02

encapsulation_Aperson

package com.oop._01encapsulation;

/**
 * 面向对象的三大特征之封装:
 *  1. 广义上的封装:定义方法是封装,定义类也是封装
 *  2. 狭义上的封装:将类中属性封装
 *         如何封装属性?
 *             --添加private访问权限修饰词,外界就不能直接访问属性了
 *             --然后提供属性有关的共有的getter和setter方法
 *
 */

public class APerson {
    //成员变量私有化
    private String name;
    private int age;
    private char gender;


    //无参构造器
    public APerson()
    {
        System.out.println("无参构造器");
    }

    //全参构造器
    public APerson(String name, int age, char gender)
    {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    //为每个成员变量提供getter/setter方法
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setAge(int age) {
        if(age<0||age>120)
        {
            System.out.println("年龄不合法");
            return;
        }
        this.age = age;
    }
    public int getAge() {
        return age;
    }



    public void setGender(char gender){
        if(gender!='男'&&gender!='女')
        {
//            System.out.println("性别不合法");
            //如果赋值有问题,可以使用下面的方式让程序中断,并提示
            throw new RuntimeException("性别不合法");
        }
        this.gender = gender;
    }
    public  char getGender() {
        return gender;
    }
}

encapsulation_APersonTest

package com.oop._01encapsulation;

/**
 * 属性的封装调用
 */

public class APersonTest {
    public static void main(String[] args) {
        //创建对象
        APerson p1 = new APerson();
        //p1.name = "小明";  name 私有化了,不可以直接访问
        //调用公有方法访问
        p1.setName("小明");
        p1.setAge(17);
        p1.setGender('女');
        //System.out.println(p1.name);  也不能直接访问,需要调用公有的方法
        System.out.println(p1.getName());
        System.out.println(p1.getAge());
        System.out.println(p1.getGender());

        p1.setGender('m');
        System.out.println(p1.getGender());




    }
}

encapsulation_BSingleton

package com.oop._01encapsulation;

/**
 *  单例模式的饿汉模式:
 *     1. 提供一个该类的,私有的,静态的属性,并在静态代码块里赋值
 *     2. 提供一个私有的构造器,避免外界直接调用构造器
 *     3. 提供一个共有的,静态的方法,来获取当前类的对象
 */

public class BSingleton {
    private static BSingleton instance;// instance 实例的含义 1usage
    static{
        instance = new BSingleton();
    }
    // 构造器私有化
    private BSingleton(){}

    public static BSingleton getInstance(){
        return instance;
    }
}

encapsulation_BSingletonTest

package com.oop._01encapsulation;

public class BSingletonTest {
    public static void main(String[] args) {
        //看是否能直接创建
        // BSingleton bsingleton = new BSingleton(); 构造器私有化,不能直接调用

        //看是否能直接访问成员
        // BSingleton.getInstance; 成员私有化了,不能直接访问

        //只能使用下面的方式获取该类的具体实例
        BSingleton bsingleton = BSingleton.getInstance();
        //再获取一次
        BSingleton bsingleton2 = BSingleton.getInstance();

        /**
         *  == :双等号,比较的是两个对象的地址
         */
        System.out.println(bsingleton == bsingleton2);

    }
}

encapsulation_Csingleton

package com.oop._01encapsulation;

/**
 * 单例模式的懒汉模式:
 *   1. 提供一个该类的,私有的,静态的属性
 *   2. 提供一个私有的构造器,避免外界直接调用构造器
 *   3. 提供一个公有的,静态的方法,来创建当前类的对象。如果不存在,说明未创建
 *   4. 懒汉模式,有线程安全隐患,比如两次调用都恰好执行到判断等于null,
 *   都会执行创建实例那一行的代码,会创建两个对象
 */

public class CSingleton {
    //私有化的静态变量
    private static CSingleton instance;
    //私有化构造器
    private CSingleton(){}
    //提供一个公有的,静态的方法,来创建当前类的对象。
    public static CSingleton getInstance(){
        //如果不存在,说明未创建
        if(instance == null){
            //创建对象,将地址存入静态变量
            instance = new CSingleton();
        }
        //返回对象的地址,之前有就用之前的,没有就用新的
        return instance;
    }
}

encapsulation_CsingletonTest

package com.oop._01encapsulation;

public class CSingletonTest {
    public static void main(String[] args) {
        //获取两次该类型的对象
        CSingleton singleton1 = CSingleton.getInstance();
        CSingleton singleton2 = CSingleton.getInstance();
        //双等号判断地址
        System.out.println(singleton1 == singleton2);
    }
}

extend_APerson

package com.oop._02extend;

/**
 *
 */

public class APerson {
    private String name;
    private int age;
    private char gender;

    public APerson(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }
}

extend_Cat

package com.oop._02extend;

/**
 * final修饰词的讲解:
 *   1. 修饰类,表示该类不能再有子类,即不能被继承了
 *   2. 修饰成员变量: 只能初始化一次,不能被再次赋值
 *   3. 修饰方法: 表示该方法不能再被重写了。
 *   4. 修饰局部变量
 */

//public final class Cat {
public class Cat {
    private final String name;

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

    public final int sum(int a, int b){

        //测试final修饰局部变量
        final int x;
        x = 100;
//        x = 101, final修饰的变量不能再次赋值
        return a+b;
    }

    // 下面的方法给name赋值,已经不是初始化了。
    // 因为想要执行该方法,那么构造器一定先执行了
//    public void setName(String name) {
//        this.name=name;
//    }
}


//不能继承Cat 因为Cat是final修饰的
//class Acat extends Cat {}

//研究父类里的方法被final修饰,是否还能重写
class BCat extends Cat {
    public BCat(String name) {
        super(name);
    }


//   public int sum(int a, int b){
//        return a+b;
//    }
}

extend_MyUtil

package com.oop._02extend;

/**
 * static修饰词
 *  1. 修饰成员变量:
 *         静态成员变量,属于类的,公共资源,使用类名,调用
 *         注意:可以使用引用变量‘.’调用,但是不合理,因为不属于对象
 *  2. 修饰方法:
 *         静态方法:属于类的,公共资源,使用类名,调用
 *         注意:可以使用引用变量‘.’调用,但是不合理,因为不属于对象
 *         静态方法不能直接访问非静态成员变量
 *         static方法 不能被重写,但是子类可以提供和父类可以一样的静态方法,各是各的。
 *  3. 修饰代码块:
 *         静态代码块,类加载时只执行一次,通常用于加载静态资源:图片、视频等
 *  4. 修饰类
 *         可以修饰内部类
 */

public class MyUtil {
    private String name;
    //定义一个水桶的容量,定义是升L
    public static int contain = 18;

    //如果想要达到每时每刻看到的静态资源是一样的,那么就应该用final修饰,即常量
    public static final  double PI = 3.14;  //static和final的顺序不固定

    public static void sum( int a, int b) {
//        不能直接访问非静态成员
//        this.name="小明";
//        addContain();
        contain = 19;
    }

    public void addContain() {
        this.contain++;
    }

    public void subContain() {
        this.contain--;
    }

    public static void  main(String[] args){
        MyUtil p1 = new MyUtil();
        //查看容量
        System.out.println(MyUtil.contain);
        p1.addContain();

        MyUtil p2 = new MyUtil();
        //注意,静态变量,使用类名调用
        System.out.println(MyUtil.contain);
        p2.subContain();
    }
}

class sub extends MyUtil{
//    @Override 添加注解后报错 因为static方法 不能被重写
//    但是子类可以提供和父类可以一样的静态方法,各是各的。
    public static void sum( int a, int b) {
//        不能直接访问非静态成员
//        this.name="小明";
//        addContain();
        contain = 19;
    }
}

extend_Student

package com.oop._02extend;

/**
 * 定义一个学生类型,有人的特征,可以继承
 *   有自己独有的特征:
 *   学号: studentId
 *   班级编号: classNo
 *
 *   在这里主要研究一下构造器:
 *    1. 子类不能继承父类的构造器
 *    2. 子类的构造器中可以使用super(有参传参)进行显式的调用父类中的某一个构造器
 *    3. super(有参传参)和this(有参传参)一样,必须放在首行首列,因此不能共存
 *    4. 子类的构造器中至少存在一个构造器调用了父类的构造器
 *    5. 为什么至少要有一个调用父类的构造器: 因为子类继承过来的属性需要初始化
 */

public class Student extends APerson{
    private String studentId;
    private String classNo;

    public String getClassNo() {
        return classNo;
    }

    public void setClassNo(String classNo) {
        this.classNo = classNo;
    }

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    //添加自己的构造器
    public Student(String studentId, String classNo){
        super( "小心", 20,  '女');
        this.studentId = studentId;
        this.classNo = classNo;
    }

    //重载一个构造器
    public Student(String name, int age, char gender, String studentId, String classNo){
        //this.name;  父类里的name属性私有化,虽然于类继承了,但是不能直接访问

        //setName方法是继承来的,并且公有,可以直接使用
        this( studentId, classNo);
        setName(name);
        setAge(age);
        setGender(gender);
//        this.studentId = studentId;
//        this.classNo = classNo;
    }

    //添加toString方法 用来显示对象的属性值
    public String toString() {
        return  "studentId='" + studentId +
                ", classNo='" + classNo +
                ", name='" + getName() +
                ", age=" + getAge() +
                ", gender=" + getGender();
    }
}

extend_StudentTest

package com.oop._02extend;

public class StudentTest {
    public static void main(String[] args) {
        //调用子类五个参数构造器
        Student xiaoming = new Student("张三", 18, '男', "2019001", "1班");
//        System.out.println(xiaoming.getName());
//        System.out.println(xiaoming.getAge());
//        System.out.println(xiaoming.getGender());
//        System.out.println(xiaoming.getStudentId());
//        System.out.println( xiaoming.getClassNo());
        System.out.println(xiaoming);

        Student xiaoxin = new Student(  "2019002", "2班");
        System.out.println(xiaoxin);
    }

}

extend_TDog

package com.oop._02extend;

/**
 * 演示 继承中的方法的重写特点
 *
 *  TDog是Animal的子类型,
 */

public class TDog extends Animal {
    public static void main(String[] args) {
        //创建一个子类对象
        TDog dog = new TDog();
        //调用继承过来的并且有访问权限的方法
        dog.sport();
    }

    //子类独有的功能
//    @Override 注解只能放在子类重写父类方法的上面,用于检测是否是重写,不是则报错
    public void noise() {
        System.out.println("汪汪汪");
    }

    // 与父类完全一致也算是重写
    @Override
    public void sport() {
        System.out.println("运动中");
    }

    //子类在重写父类的方法时,返回值类型与父类中的方法可以相同,也可以是其子类型:TDog就是Animal的子类型
    public TDog getMyClass() {
        return null;
    }

    //子类在重写父类的方法时,访问权限应该大于等于父类方法的访问权限(你的拳不够快也不够狠!)
    public String showInfo() {
        return null;
    }

    //自己独有的方法
    public String showInfo( int a) {
        return null;
    }
}

//动物类型
class Animal {
    private String color;

    //公有的,返回值类型void
    public void sport() {
        System.out.println("运动中");
    }

    //公有的,返回值类型Animal
    public Animal getMyClass() {
        return null;
    }

    //默认的,返回值类型String
    String showInfo() {
        return null;
    }
}

extend_Teacher

package com.oop._02extend;

import java.lang.reflect.Field;

/**
 * 定义一个Teacher类型,父类是Object
 */

public class Teacher {
    private String name;
    private int age;
    private char gender;

    //无参构造器
    public Teacher() {
    }

    //全参构造器
    public Teacher(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    /**
     * 重写eqyals方法
     * 1. 判断传入的是不是null
     * 2. 判断传入的是不是自己
     * 3. 判断传入的是不是同类型,如果是就转成同类型比较
     * 4. 其他任何情况都返回false;
     */

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (obj instanceof Teacher) {
            Teacher t = (Teacher) obj;
            return this.name.equals(t.name)
                    && this.age == t.age
                    && this.gender == t.gender;
        }
        return false;
    }


    /*
     toString()的作用,用于将对象的属性信息拼接起来,返回字符串
           这样就可以查看每个对象的样子了。
      但是Object类中的toString()方法,返回的是类的全名+@+hashCode值的16进制
           对我们没有太大意义,因此自定义类型是,通常都要重写
           而且,该方法在输入语句中,会自动调用。
   */
    @Override
    public String toString() {
        return "Teacher{" + "name='" + name + '\'' + ", age=" + age + ", gender=" + gender + '}';
    }

    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        System.out.println(teacher);

        //创建两个teacher
        Teacher t1 = new Teacher("张三", 18, '男');
        Teacher t2 = new Teacher("张三", 18, '男');
        System.out.println(t1 == t2); //比较地址 返回false

        boolean r = t1.equals(t2); //比较两个对象的属性是否相同
        System.out.println(r); //true

        //通过对象调用getClass(),来获取Teacher对应的描述类的对象
        Class<? extends Teacher> aClass =t1.getClass();
        System.out.println(aClass.getName());

        //获取类里的所有属性  Field字段的含义
        Field[] fields =aClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }


    }
}

polymorphism_Animal

package com.oop._03polymorphism;

public class Animal {
    private String color;
    private String name;
    private int age;

    public Animal() {}
    public Animal(String color, String name, int age){
        this.color = color;
        this.name = name;
        this.age = age;
    }

    //动物都会有发出声音的行为
    public void noise(){
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {

    public Dog(String color, String name, int age) {
        super(color, name, age);
    }

    public void noise(){
        System.out.println("汪汪汪");
    }
    public void lookHouse(){
        System.out.println("看家");
    }
}

class Cat extends Animal {

    public Cat(String color, String name, int age) {
        super(color, name, age);
    }

    public void noise(){
        System.out.println("喵喵喵");
    }
    public void catchMouse(){
        System.out.println("抓老鼠");
    }
}

polymorphism_AnimalTest

package com.oop._03polymorphism;

/**
 * 面向对象的三大特征之多态: 一个对象的多种形态。
 *         面试时可以多加一种:方法的多态(重载和重写)
 *     第一种: 向上造型(向上转型)
 *         - 父类型的变量,引入子类型的对象
 *
 *
 */

public class AnimalTest {
    public static void main(String[] args) {
        //使用Animal声明一个变量,引用一个Cat对象
        Animal a = new Cat("白色", "小花", 3);
        //调用方法:
        a.noise();//编译期间不会出现问题,因为父类里面有该方法。运行期间,执行的人对象的类型里的方法逻辑
//        a.getMouse();  调用不到该方法,因为a这个变量类型里没有该方法(编译期间,看变量类型)

        test1(a);
        Dog dog = new Dog("黑色", "大黑", 8);
        test1(dog);
    }
    //测试: 执行动物的叫声 这就是向上造型的优势所在,
    // 父类型的变量作为参数,更加灵活,可以传入不同的子类型对象
    public static void test1(Animal aminal) {
        aminal.noise();
    }
}

polymorphism_AnimalTest2

package com.oop._03polymorphism;

/**
 * 多态的另外一种形式: 向下转型。
 *    父类型的变量赋值给子类型的变量,需要强制转换
 *    该操作可能会出现失败,失败的话,就会报异常:ClassCastException 类造型异常
 *    如果想要避免失败,可以使用instanceof 关键字来进行判断:
 *      该变量指向的对象是否属于某一个类型。如果是,返回true,否则返回false
 *
 *  应用场景:
 *     多数情况下,定义方法时,形参都是父类型的变量,原因是可以接受任意子类型的对象
 *     但是有的时候,在这样的方法里的逻辑中,
 *     可能会用到该对象的独有功能,因此会涉及到向下转型
 */

public class AnimalTest2 {
    public static void main(String[] args) {
        //创建一个父类型的变量引用子类型的对象
        Animal an = new Dog("black", "小黑", 3);
        an.noise();
        //调用一下对象的独有功能//am.LookHouse();
        // 编译期间看变量类型。没有该方法,所以报
        // 只能向下转型才可以
        Dog d = (Dog)an;
        d.lookHouse();
        //上述代码没有问题,但在真正编程时,有可能写成如下代码:
        //编译期间,不报错,但是运行期间,就会报异常。
//        Cat c = (Cat)an;
//        c.catchMouse();

        //避免上述情况发生,使用instanceof即可
        if (an instanceof Cat) {  //因为an指向的是一个Dog对象,因此进不去分支
            //避免了报错
            Cat c = (Cat)an;
            c. catchMouse();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值