JAVA面向对象

对象,类和引用类型

  1. 什么是类?什么是对象?
  1. 现实世界是由很多很多对象组成的
      基于对象抽出了类
  2. 对象:真实存在的单个的个体
      类:类别/类型,代表一类个体
  3. 类中可以包含:
      3.1)所有对象所共有的属性/特征-------成员变量
      3.2)所有对象所共有的行为------------方法
  4. 一个类可以包含多个对象,同一个类的多个对象,结构相同,数据不同
  5. 类是对象的模板,对象是类的具体的实例
  1. 名词解释
    • 抽象数据类型:将不同类型的数据的集合组成一个整体来描述一种新的事物
    • 类定义了抽象数据类型的组成(成员变量),同时定义了对其实施的操作(方法)
  2. 如何创建类?如何创建对象?如何访问成员?
  • 类的定义
    class 类名{ 成员变量, 方法}
    对象
    • 使用new关键字创建对象,创建对象的过程也称为类的实例化
  • 引用类型变量
    - 简称“引用”,因其存放的是对象的地址,存储在栈中,指向存储在堆中的对象
    • 可以通过“引用”对对象进行操作,通过“引用. ”来访问成员变量和调用方法
    • 除8中基本数据类型之外,其他类型的变量都称为引用类型变量
    • 引用类型变量之间赋值赋的是地址
    • 引用可以赋值为null,表示没有指向任何对象。因此通过空的引用访问成员变量和方法会产生NullPointerException
    • 数组是引用类型
      - java中,数组属于引用数据类型
      - 数组对象在堆中存储,数组变量属于引用,存储数组对象的地址,指向数组对象。数组的元素可以看成数组对象的成员变量,只不过类型全部相同
    • 引用类型数组
      - 声明,如:Cell[] cells = new Cell[4]
      new Cell[4]仅仅是分配了4个空间,并没有创建对象
      默认初始值为null
      需使用new为每个数组元素初始化。如cells[0] = new Cell();
      数组的元素也是数组
      即二维数组,但java中并无此概念
      通常用来表示多行多列的情况
  1. 引用类型之间画等号
  1. 指向同一个对象
  2. 对其中一个引用的修改会影响另一个引用
    • eg:房子钥匙
  1. 基本类型之间画等号
    1)赋值
    2)对其中一个变量的修改不会影响另一个变量
    • eg:身份证复印件
  2. null:空,没有指向任何对象
    若引用的值为null,则该引用不能再进行任何操作了
    若操作则NullPointerException空指针异常
    ####方法的签名:方法名+参数列表
  3. 方法的重载(Overload):
  1. 在同一个类中,方法名称相同,参数列表不同
  2. 编译器在编译时(语法检查)自动根据签名来绑定调用的方法
  1. 构造方法:
  1. 常常用于给成员变量赋初值
    2) 与类同名,没有返回值类型,但也不能写void
  2. 在创建对象时被自动调用
  3. 若自己不写构造方法,则编译器默认一个无参构造方法
    若自己写了构造方法,则不再默认提供
  4. 构造方法可以重载
    6) 意义:初始化成员变量
  1. this:指代当前对象,哪个对象调方法指的就是哪个对象
    只能用在方法中,方法中访问成员变量之前默认有个this.
    构造方法中参数名与成员变量名相同时,this是必须的
    this的用法:
    1. this.成员变量名-------------访问成员变量
    2. this.方法名()---------------调用方法
    3. this()----------------------调用构造方法
  2. 引用类型数组:
  1) Cell[] cells = new Cell[4]; //创建Cell数组对象
    cells[0] = new Cell(2,5);   //创建Cell对象
	cells[1] = new Cell(2,6);
	cells[2] = new Cell(2,7);
	cells[3] = new Cell(3,6);
  2) Cell[] cells = new Cell[]{
      new Cell(2,5),
	  new Cell(2,6),
	  new Cell(2,7),
	  new Cell(3,6)
    };
  3) int[][] arr = new int[3][];
    arr[0] = new int[2];
	arr[1] = new int[3];
	arr[2] = new int[2];
	arr[1][0] = 100; //给arr中第2个元素中的第1个元素赋值为100
  4) int[][] arr = new int[3][4]; //3行4列
    for(int i=0;i<arr.length;i++){
	  for(int j=0;j<arr[i].length;j++){
	    arr[i][j] = 100;
	  }
	}

##二、对象的内存管理,继承,访问控制,static和final

  1. 内存管理:由JVM来管理---------了解
  1. 堆:
     1) 存储所有new出来的对象(包括成员变量)
     2) 垃圾:没有任何引用所指向的对象
        垃圾回收器(GC)不定时到内存中清扫垃圾,
        回收过程是透明的,并不一定一发现垃圾,则立即回收,
        调用System.gc()可以建议JVM尽快调度GC来回收垃圾
     3) 内存泄漏:不再使用的内存还没有被及时的回收
           严重的泄漏会导致系统的崩溃
           建议:对象不再使用时及时将引用设置为null
     4) 成员变量的生命周期: 创建对象时被存储在堆中,对象被回收时一并被回收
  2. 栈:
     1) 存储正在调用的方法中的所有局部变量(包括参数)
     2) 调用方法时在栈中为该方法分配一块对应的栈帧,
       栈帧中存储方法的局部变量以及参数,
       方法执行结束则栈帧被清除,局部变量一并被清除
     3) 局部变量的生命周期:调用方法时被存储在栈中,方法结束时与栈帧一并被清除
  3. 方法区:
     1) 用于存储.class字节码文件(包括方法)
     2) 方法只有一份,通过this来区分具体的对象
  1. 继承:
  1. 作用:实现代码的复用
  2. 通过extends来实现继承
  3. 父类:所有子类所共有的属性和行为
    子类:子类所特有的属性和行为
  4. 子类继承父类后,子类具有:子类的+父类的
  5. 一个父类可以有多个子类,
     一个子类只能有一个父类-------单一继承
  6. 继承具有传递性
  7. java规定: 构造子类之前必须得先构造父类
     子类构造方法中若没有调用父类的构造方法,
     则默认super()调用父类的无参构造方法,
     若子类构造方法中调用父类构造方法了,则不再默认提供
     super()调用父类构造方法必须位于子类构造的第一句
  1. super: 指代当前对象的父类对象
    super的用法:
     1)super.成员变量名---------访问父类的成员变量
     2)super.方法名()-----------调用父类的方法
     3)super()------------------调用父类的构造方法

  2. 向上造型:
     1) 父类型的引用指向子类对象
     2) 能点出来什么,看引用的类型

  3. 成员变量:
     1)存在类中,方法外
     2)创建对象时存在堆中,对象被回收时一并被回收
     3)有默认值,可不显示初始化

  4. 局部变量:
     1)存在方法中
     2)调用方法时存在栈中,方法调用结束时被清除
     3)没有默认值,必须自行设立初始值

  5. 方法的重写(Override):重新写、覆盖

  1. 发生在父子类中,方法名称相同,参数列表相同,方法体不同
  2. 重写方法被调用时,看对象的类型
    重写需遵循"两同两小一大"规则:
  3. 两同:
      1) 方法名相同
      2) 参数列表相同
  4. 两小:
      1) 子类方法的返回值类型小于或等于父类的
        1.1) void时,必须相等
        1.2) 基本类型时,必须相等
        1.3) 引用类型时,小于或等于
      2) 子类方法所抛出的异常小于或等于父类的—异常之后
  5. 一大:
      子类方法的访问权限大于或等于父类的----访问控制修饰符后
  1. 重写与重载的区别:----------常见面试题
  1. 重写(Override):
      1) 发生在父子类中,方法名称相同,参数列表相同
      2) 遵循"运行期绑定",看对象的类型调用方法
  2. 重载(Overload):
      1) 发生在一个类中,方法名称相同,参数列表不同
      2) 遵循"编译期绑定",看参数的类型绑定方法
  1. package:
      1) 作用:避免类的命名冲突
      2) 包名可以有层次结构
      3) 同包中的类不能同名,类的全称:包名.类名
      4) 包名建议:所有字母都小写
    import:
      1) 同包中的类可以直接访问,
       不同包中的类不能直接访问,想访问:
        1) 先import声明类,再直接访问类-----建议
        2) 类的全称-----------------太繁琐,不建议
  2. 访问控制修饰符:
  1. public:公开的,任何类
  2. private:私有的,本类
    3)protected:受保护的,本类、子类、同包类
  3. 默认的:什么也不写,本类、同包类
    5) 类/接口的访问修饰符只能是public和默认的
      类中的成员的访问修饰符如上4种都可以
    6)修饰类
  • public修饰的类可以被任何一个类访问
  • protected和private可以用于修饰内部类
  1. static:静态的
  1. 静态变量:
      1) 由static修饰
      2) 属于类的,存在方法区中,只有一份
      3) 常常通过类名点来访问
      4) 何时用:所有对象所共享的数据(图片、音频、视频等)
  2. 静态方法:
      1) 由static修饰
      2) 属于类的,存在方法区中,只有一份
      3) 常常通过类名点来访问
      4) 没有隐式的this传递,所以在静态方法中不能直接访问实例成员
      5) 何时用:方法的操作仅与参数相关而与对象无关
  3. 静态块:
      1) 由static修饰
      2) 在类被加载期间自动执行,因类中被加载一次,所以静态块也只执行一次
      3) 何时用:加载/初始化静态资源(图片、音频、视频等)
  1. final:最终的、不可改变的
  1. 修饰变量:变量不能被改变
      修饰成员变量,两种方式初始化:
        声明同时初始化
        构造函数中初始化
      修饰局部变量
        使用之前初始化即可
    2)常常同final一起修饰常量
      如:public static final int NUM=100;
      常量需在定义时同时初始化,建议都大写
      常量会在编译期被替换
    3) 修饰方法:方法不能被重写
    4) 修饰类:类不能被继承
  1. static final常量:
    1) 必须声明同时初始化
  1. 通过类名点来访问,不能被改变
  2. 建议:常量名所有字母都大写,多个单词用_分隔
    4) 编译器在编译时常量被直接替换为具体的值,效率高

##三、抽象类、接口和内部类
2. 抽象方法:

  1. 由abstract修饰
  2. 只有方法的定义,没有方法的具体实现(连{}都没有),用一个“;”结束
  1. 抽象类:
  1. 由abstract修饰
  2. 包含抽象方法的类必须是抽象类,不包含抽象方法的类也可以声明为抽象类—我乐意
  3. 抽象类不能被实例化
  4. 抽象类是需要被继承的,子类:
      4.1) 重写所有抽象方法-------常用
      4.2) 也声明为抽象类---------不常用
  5. 抽象类的意义:
      5.1) 封装子类所共有的属性和行为-------代码复用
      5.2) 为所有子类提供一种统一的类型-----向上造型
      5.3) 特别意义:可以包含抽象方法,为所有子类提供一个统一的入口
        子类可以有不同的实现,但方法的定义是一致的
抽象类实例:
//求一组图形中的最大面积
public class ShapeTest {
	public static void main(String[] args) {
		//Shape s = new Shape(); //编译错误,抽象类不能被实例化
		Shape[] shapes = new Shape[4]; //创建Shape数组对象
		shapes[0] = new Circle(1); //向上造型
		shapes[1] = new Circle(2); //大
		shapes[2] = new Square(1);
		shapes[3] = new Square(2);
		maxArea(shapes);
	}
	public static void maxArea(Shape[] shapes){
		double max = shapes[0].area();
		int maxIndex = 0; //最大面积下标
		for(int i=1;i<shapes.length;i++){
			double area = shapes[i].area();
			if(area>max){
				max=area;
				maxIndex=i;
			}
		}
		System.out.println("最大面积为:"+max+",所在下标为:"+maxIndex);
	}
}
abstract class Shape{ //抽象类
	protected double c; //周长
	public abstract double area(); //抽象方法
}
class Circle extends Shape{
	public Circle(double c){
		this.c = c;
	}
	public double area(){ //重写抽象方法
		return 0.0796*c*c; //0.0625
	}
}
class Square extends Shape{
	public Square(double c){
		this.c = c;
	}
	public double area(){
		return 0.0625*c*c;
	}
}
  1. 接口:
  1. 是一个标准、规范--------制定方,遵守了这个标准,就能干某件事(造型)
  2. 接口是一种数据类型(引用类型)
  3. 由interface定义
  4. 只能包含常量和抽象方法
  5. 接口不能被实例化
  6. 接口是需要被实现的,实现类:
     必须重写接口中的所有抽象方法
  7. 一个类可以实现多个接口,用逗号分隔,若又继承又实现时,应先继承后实现
    8) 接口可以继承接口
    4. 抽象类和接口的区别:
    1) 一个类只能继承一个抽象类,但可以实现多个接口。
    2) 抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的。
    3) 子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。
    4) 而子类实现接口则必须实现接口中的所有抽象方法。
  1. 多态:
  1. 多态的意义:
      1.1) 同一类型的引用,指向不同的对象时,有不同的实现
       -----行为的多态:cut(),run(),study(),teach()…
      1.2) 同一个对象,被造型为不同的类型时,有不同的功能
       -----对象的多态:我,水…
  2. 向上造型:
      2.1) 父类型的引用指向子类的对象
      2.2) 能造型成为的类型有: 父类+它所实现的接口
      2.3) 能点出来什么,看引用的类型
  3. 强制类型转换,成功的条件只有两种:
      3.1) 引用所指向的对象,就是该类型
      3.2) 引用所指向的对象,实现了该接口
  4. 若不符合如上两个条件,则发生ClassCastException类型转换异常
     建议:在强转之前先通过instanceof判断引用指向的对象是否是某种类型
     
    ####成员内部类: 应用率不高
  5. 类中套类,外面的称为外部类Outer,里面的称为内部类Inner
  6. 内部类通常只服务于外部类,对外不具备可见性
  7. 内部类对象通常是在外部类中创建的
  8. 内部类中可以直接访问外部类的成员(包括私有的)
     内部类中有一个隐式的引用指向了创建它的外部类对象
       eg: 外部类名.this
     5) 代码说明
外部类:

public class Outer {

private int time; private Inner inner; Outer(int time){

this.time=time; inner=new Inner(); inner.timeInc();

}

public void printTime(){ System.out.println(time);

}

内部类:

class Inner{

public void timeInc(){ time++;

}}}

测试代码:

Outer out=new Outer(100); out.printTime();

输出应为 101

此例中 timeInc()的完整调用应为 Outer.this.timeInc():

其中 Outer 是一个隐式的引用,指向对象 out this 也是一个隐式的引用,指向对象 inner。

####匿名内部类:

  1. 若想创建一个类(子类)的对象,并且对象只被创建一次,
    此时该类可以不必命名,称为匿名内部类
  2. 匿名内部类中若想访问外部的变量,该变量必须是final的
    3) 所有类都有独立的.class。包括内部类
  接口:

public interface Action { public void execute();
}

父类:

public class Super { public void print(){
System.out.println("hello");
}}

匿名内部类:

public class AnonymousInnerClass {
Action action=new Action(){ public void execute(){
System.out.println("Hello, World");
}};
Super sup=new Super(){ public void print(){
System.out.println("Hello, My World");
}};
public void execute(){ action.execute();
}
public void print(){ sup.print();

}}

测试类:

public static void main(String[] args) {

AnonymousInnerClass test=new AnonymousInnerClass(); test.execute();

test.print();

}

##面向对象三大特征:

  1. 封装:
  1. 类: 封装的是对象的属性和行为
  2. 方法: 封装的是具体的业务逻辑功能实现
  3. 访问控制修饰符: 封装的是访问的权限
  4. 封装的意义:
      对外提供可调用的,稳定的功能
      封装容易变化的,具体的实现细节,外界不可访问。其意义在于:
      降低代码出错的可能性,便于维护
      当内部的实现细节改变时,只要保证对外的功能定义不变,其他模块就不会因此而受到牵连
  1. 继承:
  1. 代码的复用
  2. 父类/基类:所有子类所共有的属性和行为
     子类/派生类:子类所特有的属性和行为
  3. 子类继承父类之后,子类具有:父类的+子类的
  4. 传递性、单一继承、多接口实现
  1. 多态:
  1. 意义:行为的多态、对象的多态
  2. 向上造型、强制类型转换、instanceof判断
  3. 多态的表现形式:
      3.1) 重写(依据对象的不同来实现多态)
      3.2) 重载(依据参数的不同来实现多态)
    ##面向对象设计规则
  • 将公共的属性和行为抽象到父类中
  • 所有子类行为一样,写成普通方法;子类行为不一样,写成抽象方法。(如有抽象方法,则可确定为抽象类)
  • 符合既是也是原则,使用接口(意即需要继承多个父类时)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值