深入理解java中的面向对象

类和对象

面向过程:当我们需要实现一个功能时,我们专注于实现过程的每一个步骤即实现的过程。
面向对象:实现功能时,我们不关注具体的实现步骤,而是找一个已经具有此功能的人,去帮我们实现这个功能。
那么什么是对象?
Object:对象,东西,万物皆为对象。
同类型的东西,我们把它抽象成一个类。类是对象的模板、图纸,是对象的数据结构定义。
通常一个类是不能直接被使用的,需要根据该类创建一个对象才能使用,那么我们首先要定义一个类

定义类

  1. 其实定义类,就是在描述事物,就是在定义属性(变量)和方法(函数)。
  2. 类中可以声明:属性,方法,构造器;
  • 属性(变量)分为:实例变量,局部变量;
  • 实例变量:用于声明对象的结构的,在创建对象时候分配内存,每个对象有一份!实例变量(对 象属性)在堆中分配,并作用于整个类中,实例变量有默认值,不初始化也能参与运算;
  • 局部变量在栈中分配,作用于方法或语句中,必须初始化,有值才能运算。

我们来构造一个学生类:
分析他们的属性和行为
构建学生类
1.属性(特性)
性别:
学号:
专业:
2.动作(行为)
上课()
吃饭()
睡觉()

那么对应到java类中:

    成员变量:(属性)
        int sex;性别
        int number;学号
        String major;专业
    成员方法:(动作或者行为)
        public void learning(){} 上课
        public void eat(){} 吃饭
        public void sleep(){} 睡觉

1.成员变量(属性)是直接定义到类里面的,方法外面
2.成员方法(动作和行为)不要static修饰

定义在方法中的变量称为局部变量。
成员变量和局部变量的区别:

  1. 内存位置不一样(了解)
    成员变量存在内存的堆内存中
    局部变量存放在内存的栈内存中
  2. 定义的位置不同:(重点)
    成员变量:类中方法之外
    局部变量:方法内部
  3. 作用范围不一样:(重点)
    成员变量:作用范围存在整个类中
    局部变量:只能作用在对应方法中,出了方法就没用了
  4. 默认值不一样(重点)
    成员变量:如果没有赋值,则会自动补上默认值
    局部变量:没有默认值,需要自己手动补全(参数也是一种局部变量,他的赋值是由调用者提供的)
  5. 生命周期不一样(了解)
    成员变量:根据对象创建时生成,被GC回收时消失
    局部变量:根据方法入栈时创建,出栈时就消失了

Java面向对象的三大特征

封装,继承,多态:
1.封装---属性私有化,行为公开化
权限关键字 public procted default private
2.继承---父子类(将一些重复的代码抽取到父类当中,单一继承)
3.多态---向上向下造型

封装(访问控制):

封装:将数据封装到类的内部,将算法封装到方法中。

  1. 封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其 访问,通常有两种访问方式:set 设置,get 获取。
  2. 封装结果:存在但是不可见。
  3. public:任何位置可见,可以修饰:类、成员属性、成员方法、内部类、跨包访问类 (需要使用import 语句导入),成员属性 == 成员变量。
  4. protected:当前包中可见,子类中可见。可以修饰:成员属性、成员方法、内部类(只 能在类体中使用,不能修饰类) 。
  5. default(默认的):当前包内部可见,就是没有任何修饰词,可以修饰:类、成员属性、成员方 法、内部类,但在实际项目中很少使用。默认类(包内类)的访问范围:当前包内部可见, 不能在其他包中访问类,访问受限!main 方法若定在默认类中 JVM 将找不到,无法执行, 因此必定在public 类中。
  6. private:仅仅在类内部可见。可以修饰:成员属性、成员方法、内部类(只能在类体 中使用,不能修饰类) 。私有的方法不能继承,也不能重写。

    构建标准JavaBean

使用private关键字修饰需要被保护的成员变量,外部无法随意访问
只有本类可以正常使用该变量
外部想访问需要通过Getter/Setter方法

getXX和setXX 命名规则

  • 对于 set方法不能有返回值,参数值必须与成员变量类型保持一致
  • 对于 get方法不能有参数值,返回值必须返回成员变量且返回值类型需要与成员变量保持一致

构造器

  • 用于创建对象并初始化对象属性的方法,叫“构造方法”,也叫“构造器”;构造器在类 中定义。
  • 构造方法的方法名和类名一样,无返回值(void也没有)public修饰
    N个属性:2^N+1个构造方法
  • 方法的重载:方法名相同,参数列表不同
    1.重载方法不能有返回值
    2.如果没有写构造方法 那么系统会赠送一个无参构造方法,如果我们写了任何构造方法 系统将不再赠送
  • new对象其实就是使用该类的无参构造

标准javaBean规范
属性私有化
行为公开化

//构建标准JavaBean
public class Person {
    private String name;
    private String age;
    //无参构造方法
    public Person(){

    }
    //全参构造方法
    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }
    //get方法
    public String getName() {
        return name;
    }
    //set方法
    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

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

继承

父子类:将重复的代码提取到父类当中,单一继承

  • java中不支持多继承,一个子类只能继承一个父类,一个父类可以存在多个子类
  • 父子类中:
    • 父类无法访问子类的属性和方法
    • 子类可以访问全部父类的属性和方法(当子类没有的属性时,会自动向上查找)
    • 出现同名的变量遵循就近原则
      super.method();     //使用父类的方法super.
      System.out.println(this.num);   //调用自己的成员变量使用this关键字.
      System.out.println(super.num);   //想使用父类的变量super.

方法的重写(override):方法名相同,参数列表也相同
重写发生在父子类中
遵循“两同两小一大”

  • 两同:方法名相同,参数列表相同
  • 两小:子类方法的返回值类型要小于或等于父类
  1. 父类为void子类必须要相等
  2. 父类为基本类型时,必须要相等
  3. 父类为引用类型时,子类小于或者等于父类
    子类抛出的异常要小于等于父类
  • 一大:
  1. 子类访问权限大于等于父类 --public >protected>private

方法的重载(overload):方法名相同,参数列表不同

多态

向上造型:父类引用指向子类对象(子类型,实例也是子类的实例化);
当发生向上造型时,调用同名方法程序会先到父类中寻找该方法,再到子类中寻找

Person p = new Studnet();

代码中的多态,其实就是父类引用指向子类对象(向上造型)

  • 格式
    父类名称 对象名 = new 子类名称();

    或者

    接口名 对象名 = new 实现类名称();

  • 使用多态访问成员变量的形式:

    1. 对于直接同过对象访问变量:要看等号左边部分,左边部分是谁就优先用谁,没有则往上找
    2. 间接访问成员变量:该方法属于谁,优先用谁,没有则往上找
  • 访问成员方法:

    • 看new 的是谁则优先用谁,没有则往上找
  • 口诀:

    • 成员方法:编译看左边,运行看右边
    • 成员变量:编译看左边,运行还是看左边
  • 为什么要使用向上造型:

    • 向上造型为我提供了统一的数据类型

向下造型:子类引用指向父类对象(父类型,实例是子类的实例化);
向下造型格式:

  1. 父类名称 父类对象名 = NEW 子类名称(); double a = 10
  2. 子类名称 子类对象名 = (子类对象名)父类对象 (相当于一个数据的还原) int b = (int)10.0
    instanceof关键字 用来判断一个父类引用的对象,他本来的子类是什么

用来判断一个对象能不能被当做后面类型的实例 得到一个boolean值

格式  对象 instanceof 类名称
Person p1 = new Student();

Student s1 = (Student)p1;

但有运行出错的情况:

Person p2 = new Person();

Son s2 = (Son)f2;//编译无错但运行会出现错误

在不确定父类引用是否指向子类对象时,可以用instanceof来判断:

if(p3 instanceof Student){

     Student s3 = (Student)p3;

}

常用关键字

static静态修饰词:
可以修饰变量,可以修饰方法
static修饰的变量或者方法在程序加载时候就被加载到内存中,且只被加载一次

使用static修饰的变量不再属于对象,而是全局共享的数据
 静态变量的调用:
  1>对象.变量     ----不推荐
  2>类名.变量     ----推荐
 静态方法不能使用非静态资源

静态块:格式static{ }
静态块加载时间为类加载时加载时 执行
静态块只在类加载时候 加载一次
何时使用:加载/初始化静态资源(视频,音频,图片等)

void 标注无返回值
有返回值方法格式:修饰符 返回值类型 方法名(参数列表){代码块 return结果};
形参 和 实参
形参:方法中标注的参数即为形参
实参;调用方法时实际传过去的参数

public class Method_Demo2 {
    public static void main(String[] args) {
        f1();
        f2(5);
        double a = f3();
        f4("Hello");
    }

    //  无参无返回值方法
    private static void f1() {
        System.out.println("Hello World");
    }

    //  有参有返回值方法
    private static int f2(int x) {
        int a = 5+x;
        return a;
    }

    //  无参有返回值方法
    private static double f3() {
        double a = 2.5;
        return a;
    }
    //有参无返回值方法
    private static void f4(String str) {
        System.out.println(str);
    }
}

package:

  1. 避免了类名的冲突
  2. 同包下的类名不能相同,不同包下面的类名可以相同
  3. 对于一个类名来说他的全称:包名+类名
  4. 对于包名最好全部都是小写字母

import:

  • 同包中的类可以直接访问,不同包中的类不能直接访问
  • 不同包中类访问方式:
    1. 使用import关键字 先声明再使用
    2. 使用类的全称 --不建议

public protected private 访问修饰符

  • public 表示共用的,任何类都可以访问

  • protected 表示受保护的 访问范围可以被 本类 同包类 子类 访问

  • default什么都不写:表示默认级别 访问范围 本类 同包类

  • private:表示私有 访问范围本类

    1)对于类来说修饰词只有public或默认两种级别
    2)类里面的成员可以以上四种修饰词修饰

  • 访问权限能够用下一级别的修饰词尽量使用下一级别(如可以用public用protected)

final:最终的

  • 修饰变量需要马上赋值,且不能被改变
  • 修饰方法:方法不能被重写 可以被重载
  • 修饰类:类不能被继承

static final修饰的变量称为常量

  1. 声明的同时必须要赋值
  2. 访问 通过类名.常量名
  3. 常量名的声明:建议全部使用大写字母 多个字母使用下划线连接 WIDTH_HEIGHT
  4. 在编译时 常量直接替换为数字
    如果一个数据不被改变且经常会用到可以把他做成一个常量

abstrat

  • 抽象方法:使用关键字abstract修饰 没有方法体

  • 抽象类:抽象方法所在的类,必须为抽象类,格式 直接在class前面加abstract修饰词

  • 抽象方法和抽象类的特点:

    • 抽象类不能被实例化(不能被new出来)
    • 子类必须要重写父类里面的抽象方法
    • 重写抽象方法时需要去掉abstract关键字
    • 抽象类中可以没有抽象方法
    • 但是有抽象方法的类一定是抽象类
    • abstract只能用来修饰方法或者类
  • 抽象类存在的意义:

    • 1.分装子类共有的行为
    • 2.为所有子类提供了统一的类型 ---向上造型使用的
    • 3.可以包含抽象方法,为所有子类提供了统一的入口,子类具体的实现不同,但方法定义相同

成员内部类(实际使用率很低)

  1. 类中套类,外面的类称为Outer,里面的类称为Inner
  2. 内部类通常只服务于外部类,对外没有可见性
  3. 内部类通常是在外部类中创建的
  4. 内部类可以访问外部类私有属性,因为内部类中有个隐式的引用指向创建他的外部类对象:外部类名.this

内部类的主要作用如下:

  1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类
  2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据
  3. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便

抽象类和接口

抽象类可以继承普通类
抽象类可以实现接口,且不用重写接口中的方法
抽象类可以被承

接口  可以解决类的单一继承
接口的定义: 接口是多个类的公共规范 接口也是一种数据类型,其中最重要的就是里面的抽象方法
接口的格式
/**
 *     public interface 接口名{
 *         //接口内容
 *     }
 *      接口编译后也是.class
 *
 *      接口中内容:
 *        java 1.7版本接口内容
 *          1.常量
 *          2.抽象方法
 *       java 1.8
 *          3.默认方法
 *          4.静态方法
 *       java 1.9
 *          5 私有方法


     从Java 1.8开始可以添加默认方法
 *   接口中默认方法的格式:
 *    public default 返回值类型 方法名(参数){
 *        方法体
 *    };

 *  默认方法的添加可以解决接口升级的问题
 *
 *  从Java1.8开始可以添加静态方法:
 *  格式:
 *      public static 返回值 方法名(参数列表){
 *          方法体
 *      }

 *  java 1.9开始允许定义私有方法:
 *   格式:
 *   静态私有方法
 *    private static 返回值类型 方法名(){
 *        方法体
 *    }
 *    默认私有方法
 *    private 返回值类型 方法名(参数列表){
 *        方法体
 *    }
 *   私有方法的调用:都是直接使用方法名调用
 *   创建私有方法为了解决代码重复

 *
 *
 */

接口中的数据都是常量:
  pubic final static 数据类型 常量名  = 常量值
  接口中的数据都为常量:不详细写清楚也会自动补齐
接口中的方法为抽象方法
 想使用接口中的方法需要实例化接口的实现类,实现类需要重写接口中的方法,
 如果不全部重写抽象方法,实现类需要为抽象类

 1.接口中默认方法的调用:可以通过实现类的对象,直接调用
 2.接口中的默认方法,可以被实现类覆盖重写重写

  静态方法的调用 接口名.方法名(参数列表)
   注意:不能同实现类对象.静态方法

注意:接口可以继承接口,接口不可以实现接口,接口可以多继承,一个类可以实现多个接口,接口无法被实例化

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务