JAVA基础之面向对象(个人学习笔记,更新修改中)

面向对象笔记


面向对象

对象:一组有关信息(数据),表示一个事物。代表软件中的一个事物个体。

eg"Tom, ,男 ,100.0"代表了个员工个体。

类:用于定义对象的数据结构,约定对象的内容。

eg:一个员工包括4个数据

分别是姓名,年龄,性别,薪水

类就是类型,类不是个体,不是具体东西

属性:是属于对象的变量,每个对象都有一份

属性是在类上定义的

代码:类的定义

egclass Emp{

String name;//姓名

int age;//年龄

char gender;//性别

double salary;//薪资

}

定义方法

public static int sum ( int num1 , int num2 ) { }

方法调用

int result = sum(56); 

int a = 50, b = 60;

int result = sum ( a , b );

抽象数据类型:将不同类型的数据的集合组成一个整体用来描述一种新的事物。

类不但定义了抽象数据类型的组成,同时还定义了可以对该类型实施的操作(方法)。

使用类的目的:管理一组信息

类的定义包括成员变量和定义的方法的定义

java语言中,类的成员变量的定义可以使用如下语法,类名首字母需大写

class 类名{

成员变量类型 变量名称

}

除了基本类型都是引用类型,引用类型自动初始化为null

局部变量:在栈中分配(在循环里面声明的变量)

对象:在堆中分配

new运算在堆中开辟空间

成员变量:创建对象以后称为对象的属性,也就是属于对象的数据,也称为实例变量(如Cell方法中的rowcol

 


程序=数据+算法

new :运算符,只分配堆内存数据空间,保存数据

new 数组:分配数组空间,堆内存

new 类 :分配对象空间,堆内存,按照类的声明,按照类的属性分配内存空间

当内存不够分配的时候,会溢出(内存泄漏)、

内存:分为3个主要区域

栈:分配局部变量

局部变量:在方法中声明的变量,可以是基本类型也可以是引用类型

堆:存储对象,所有对象都在堆中。对象的属性就是在堆中分配的,属于对象的变量,对象的属性可以是基本类型也可以是引用类型

方法区:存储类的信息。class加载区域,静态区

引用类型:除了基本类型(8种基本来型),都是引用类型。

******* 引用类型 与 基本类型的差异 ********

基本类型的值 就是本身的值      eg:   int a=5 //a的值就是5

引用类型的值 是一个对象的地址是 引用类型变量通过地址间接引用了对象    

 egCell c=new Cell()

  严禁说法:c的值是new创建对象的首地址, c通过这个首地址引用了堆内存中的Cell类型对象

  不严禁说法:c的值是对象

当使用 赋值进行赋值的时候

Cell c2==c;

严禁说法:将c的值(地址值)赋值给变量c2c2的值与c相同,都引用同一个对象

 

null值现象

应用类型特有现象,表示变量不引用任何对象的状态!此时有变量,没有对象,

如果访问值是null的引用变量的属性和方法,将发生空指针异常

空指针异常     ***********

1,有引用变量

2,变量值null,不引用任何对象

3,访问了变量的属性,方法,成员

满足123时候发生空指针异常

如何解决空指针异常

1,访问属性和方法之前,使引用变量合理的引用对象就可以解决空指针异常

2,在访问方格,属性,成员之前检查引用变量是否为null,如果不为null再访问

错误:

1,对象是空,会发生空指针异常!//对象不能说为空

2,变量为空,一定为发生空指针异常!//不访问就不会发生空指针异常

方法:封装计算过程

对象的方法:

1,是封装了对对象数据进行计算操作的算法

2,方法实现了定义的功能(动作)

为啥要用方法:就是封装功能,使用功能能够重用

 

使用方法:

在类中为对象定义方法,实现对象数据的计算功能

class Cell{

int row;

int col;

public void drop(){//下落 功能:算法当前对象的行+1

row++;

}

}

使用方法:调用方法,在对象上调用方法,实现计算功能

Cell c=new Cell();

c.row=0;

c.col=4;

c.drop();//调用对象的方法,执行下落算法

System.out.println(c.row);//1

//方法好处是可以重用

c.drop();

c.drop();

c.drop();

方法的重载:

在类中定义方法名一样,方法参数不同的方法

为啥要用重载:

为了提供方法名一样的不用功能的方法

eg:方块 有两种下落方式:1)一格一格下落,2)直接下落到底层

方法重载语法:

在类中:

1,方法名一样

2,方法参数类型列表一定不同

Cell增加另一种下落方法,利用重载语句

class Cell{//声明了两个重载的方法drop

int row,col;

public void drop(){}//实现下落一步

public void drop(int step){}//实现下落n

}

 

构造方法语法结构

构造方法是在类中定义的方法,不同于其他的方法,构造方法的定义有如下两点规则:

1,构造方法的名称必须与类名相同

2,构造方法没有返回值,但也不能写void

语法:

[访问修饰符]类名(){

构造体;

}

 

构造方法常用于实现对象成员变量的初始化

class Cell{

int rot,col;

public Cell(int row1,int col1){

row=row1;

col=col1;

}

}

使用调用构造器,必须使用new元素调用构造其

 

构造器方法:

构造器方法(构造器)与方法

1,用途不同

构造方法:初始化对象的属性

格子的构造器用于初始化格子的属性

方法:用于封装功能算法

格子的方法drop用于做下落计算。

2,语法不同:

构造方法:名字于类名一样,不能定义返回值

使用new运算符调用,用于创建对象

方法:名字一般与类名不同,必须定义返回值

使用对象引用.方法名调用。对这个对象进行计算

方法和构造方法没有关系。详见JSDMy1503_OOP/src/day02/gouzaoqi.java

 

this关键字

this==这个是代词,代表当前事物

this在方法运行期间代表调用方法的当前对象本身,是指当前对象的引用变量

****在方法运行期间

****指向当前对象的引用变量

this代表调用方法时的这个对象!

何时使用:

1,当局部变量实例变量(属性)同名时候,this.实例变量方式区别于局部变量

eg

class Cell{

int row,col;//实例变量 属性

public void drop(){

int row =1//局部变量

row //不加前缀,是局部变量

this.row//是实例变量

}

}

成员变量>=“实例变量”==对象属性

任何一个类都必须含有构造方法(构造器)。

如果源程序中没有定义,编译器在编译时将为其添加一个无参数的空构造器。

当定义了构造方法后,java编译器将不再添加默认的构造方法。

 

构造器可以重载

构造器名字相同,参数不同

一个类中可以定义多个构造器

为啥要构造器重载

构造器:初始化对象,方便创建对象

方便用多种方式创建对象:构造器重载

 

class Cell{

int roe,col;

public Cell(){//无参构造器

row=(int)(Math.random()*10+10);

col=(int)(Math.random()*10+10);

}

public Cell(int row,int col){//有参构造器

this.row=row;

this.col=col;

}

}

 

数组

java中没有真正的二维数组

二维数组的迭代  迭代==遍历

for(int i=0;i<arr.length;i++){

System.out.println();

for(int j=0;j<arr[i].length;j++){

System.out.print(arr[i][j]+" ");

}

}


1,内存管理:

编译好的java程序需要运行在JVM

JVM内存分为方法区三个区域,分别用于存储不同的数据。

java创建了大量的对象,这些对象都被引用,无法被GC回收,会造成内存泄漏

2,变量的生存周期

局部变量也称为临时变量,生存周期为作用域,离开作用域时会及时销毁

java的编程习惯是,变量的作用域越小越好

成员变量:实例变量和静态变量

成员变量>=“实例变量”==对象属性

局部变量 比较 实例变量(对象属性)

局部变量:

定在方法中

没有默认值,必须自行设定初始值

方法被调用,存在栈中,方法调用结束,从栈中清楚

变量成员:

定义在类中,方法外

有默认初始值,可以不显示初始值

所在类被实例化后,存在堆中,对象被回收时,成员变量消失

方法区,存放所有的类

继承

通过extends关键字可以实现类的继承

构造器名称跟类名一样

构造器:

1,类一定有构造器

2,构造器不能继承

3java中子类的构造器一定调用父类构造器

 a,子类构造器中默认情况下自动调用父类无参数构造器(隐含规则)

 b,如果父类没有无参数构造器,就必须使用super()调用父类有参数构造器

 

建议:凡是是类都要有构造器,方便子类的继承!

class Noo{

//public Noo(){}//****无参构造器******

public Noo(int n){

System.out.println("Call Noo(n");

}

}

class Moo extends Noo{//Moo会自动调用父类的无参构造器,但是父类没有无参构造器,出现编译错误!

//解决方法:1,在父类中添加无参构造器2,在子类构造使用super(5)调用父类有参构造器

public Moo(){

super(5);

}

}

super.的用法   2super()//调用父类构造器

 1super. //在子类对象中父类型中声明的属性,方法

public class demo10 {

public static void main(String[] args) {

Boo boo=new Boo();

boo.test();

}

}

class Aoo{//父类int times=1;}

class Boo extends Aoo{//子类

int times=8;

public void test(){

int times=9;

//就近原则

System.out.println(times);//9

System.out.println(this.times);//8

System.out.println(super.times);//1

}

}

this也有两种用途

this,   代表当前对象,访问当前对象的属性和方法

this() 在类的构造器中调用本来的其他构造器实现构造器的重用,简化代码  egdemo11

只能在构造器中使用,并且只能用于构造器的第一行

this()和super()互斥

 

父类的引用指向子类型的对象

一个子类的对象可以向上造型为父类的类型。即,定义父类型的引用可以指向字类的对象

父类的引用可以指向子类的对象,但通过父类的引用只能访问父类所定义的成员,不能访问子类扩展的对象

 


重写:

java语言中,子类可以重写(覆盖)继承自父类的方法,即方法名和参数列表与父类的方法相同,但是方法的实现不同。

当子类重写了父类的方法后,该重写方法被调用时(无论是通过子类的引用调用还是通过父类的引用调用),运行的都是子类重写后的版本。

通过super.可调用父类的方法,

重写(override)重载(overload)的区别

重载:一个类在当前类中声明方法和父类中继承的方法中,方法名相同的方法,参数列表不同

重载是指在一个类中定义多个方法名相同但参数列表不同的方法,在编译时

根据参数的个数和类型来决定绑定哪个方法

1,方法名相同但参数列表不同

2,本质上完全不用

根据方法名+参数类型类表=方法签名

调用的规则:根据方法签名识别执行

重写:发生在两个类中,并且是子类和父类的父关系,子类和父类的签名相同 ,子类修改父类的行为方法

有继承为前提,如果不能继承(私有方法不能继承,),就不会发生重写,重写是指在子类中定义和父类完全相同的方法,在程序运行时,根据对象的

类型不同(而不是引用类型)而调用不同的版本

***可以通过super访问父类的方法。

1,方法名一样

2,参数列表一样

3,修饰词可以放大,保护的可以放大为公共的

4,返回值可以返回小类型(大多都一样)

5,异常可以更加小

大多情况下:子类声明方法与父类完全一样

6,调用时候:调用子类对象的重写方法

重载是看类型 在编译期绑定

重写是看对象 在运行期绑定

包的概念

定义类时需要指定类的名称,但如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突的问题,这会给组件及团队的合作造成很大的麻烦

包名也可以有层次结构,在一个包中可以包含另外一个包,

import语句语法:import类的全局限定命名()

package day04;

   import day04.sub.Point;

    public class dome05 {

/**

 * day04中访问day04.sub包中声明Point

 * dome05Point不在同一个包中

 */

public static void main(String[] args) {

//1)使用全名限定名(类的全名)访问类

day04.sub.Point p=new day04.sub.Point(5,6);

//2)使用import导入day04.sub.Point导入以后就可以省略包名

Point p2=new Point(7,8);//以上两种方式都可以实现跨包访问类

//2import更加方便

//1)何时使用:当前包中的类于导入的类重名,只能使用1)方式

Moo m=new Moo();//就近原则,m使用了本包中的Moo

day04.sub.Moo m2=new day04.sub.Moo();//使用day04.sub包中的Moo

}

}

class Moo{

}

 

访问修饰符:

封装的意义:

1,降低代码出错的可能性,更便于维护。

2,当内部实现细节改变时,只要保证对外的功能定义不变,其他的模块不需要更改。在软件系统中,封装常常需要依靠一些访问控制修饰符来实现。

privatepublic为最最常用的两个访问控制修饰符

private修饰的成员变量和方法仅仅只能在本类中调用

protected修饰的成员变量和方法可以被子类及同一个包中的类使用

默认访问控制即不书写任何访问控制符,默认访问控制的成员变量和方法可以被同一个包中的类调用

public修饰的成员变量和方法可以在任何地方调用

私有的目的:是封装,保护

修饰词使用原则

1,尽可能使用private修饰属性和方法,尽量封装在清楚该用哪个修饰词时候,首先用private

2,如果是给子类留下属性或方法,使用protected

3,确实是公共属性或方法,需要被其他类访问的时候使用public

4,默认的修饰词,尽量不用,几乎不用

总之:尽量封装

 

public protected 默认 private

 

 

 

 


多态:

各种各样的情况都会发生!

static修饰成员变量

1,在类中使用static修饰的成员变量

2,类加载期间在方法区初始化

3,在软件运行期间,只有一份的变量

4,一般使用类名,变量名访问静态变量,很少使用对象.变量名访问静态变量

5,静态变量(静态变量成员)称为属于类的变量,是类的全体实例共享的同一份变量

6.凡是软件运行期间的一份数据可以使用静态变量存储

   它所修饰的成员变量不属于对象的数据结构,而是属于类的变量,通常通过类名来引用static成员。

当创建对象后,成员变量是存储在堆中的,而static成员变量和类的信息一起存储在方法区而不是在堆中

static方法中也不能访问非static成员(对象成员)

成员变量:

1,实例变量:是属于对象的变量

2,静态变量:是属于类的变量,只有一份

 

静态方法:

1,属于类的方法

2,一般使用类名.方法名

3,不需要创建对象直接类名.方法名

优点:使用方法名直接调用方法,不用创建对象直接执行方法,调用方便egMath.random;

非静态方法:

优点:可以使用当前对象的数据

必须使用对象调用,当前对象默认传递this作为当前对象数据

 

大多使用非静态方法,方便计算,确实与当前对象无关的对象,在使用静态方法

 

 

因为静态方法中没有当前对象的引用this,在静态方法中不能直接访问当前的对象的属性,方法。

静态方法中没有this

使用建议

1,当一个方法在运行期间使用了当前对象的数据this)时候这个方法,这个方法要声明为非静态

2,当一个方法在运算期间与当前对象数据(属性)无关,这个方法就可以声明为静态方法

eg:计算一个整数是否是10的倍数,是静态还是非静态。计算过程于任何对象无关所以可以定为静态放法

******** 与当前对象无关用静态 ******

静态方法:属于类的,于当前对象昂无关方法

 

static

static块:属于类的代码块,

静态代码块,在类中声明的语句块!静态代码块中可以使用任何语句

在类加载期间执行,因为java类只加载一次,所以静态代码块只执行一次

用于:加载一次性资源(图片,声音等)

class Apple{

static{//静态代码块,在类中声明的语句块!静态代码块中可以使用任何语句

//在类加载期间执行,因为java类只加载一次,所以静态代码块只执行一次

System.out.println("Hello Apple!");

}

}

 

final关键字

final修饰的成员变量,意为不可改变,初始化后不可改变

两种初始化方式:

1,声明变量同时初始化

  2,使用赋值语句第一次赋值,初始化

 3,使用构造器初始化

 4,方法调用时候参数传递初始化

final关键字也可以修饰局部变量,使用之前初始化即可

final关键字修饰的方法不可以被重写:防止子类在定义新方法时造成的不经意重写

final关键词修饰的类不能被继承

 

final的优点:

1,可以保护变量的值不被修改

2,可避免意外被改变出现的错误

3,可以保护类不被继承修改,可以监制滥用继承对系统造成的危害

 

final:初始化以后不可以再改变

static:使用类只有一份

jdk中的一些基础类库被定义为final的,egStringMathIntegerDouble等等

 

static final常量

static final 修饰的成员变量称为常量,必须声明同时初始化,并且不可被改变。常量建议所有字母大写。

 

 

 

 


 

一个类如果没有父类,就继承Object,任何类的最终父类都继承于Object

任何类型都是Object:啥都是东西====一切皆对象(唯物主义)

                <--:

                    |<--坦克

        |<--交通工具|

Object|        |<--汽车

      |< --Cell

抽象类(abstract):抽象类不可以实例化,即不可以new

抽象方法可以有参数,有返回值

抽象类只能被继承,(就是用来被继承的)

abstractfinal关键字不可以同时用于修饰同一个类,

一个类继承抽象类后,必须重写其抽象方法,不同的子类可以有不同的实现

一个程序中只有一个公有类 public class mingzi 

即使一个类中没有抽象方法,也可以定义为抽象类

总结:

1,如果泛化出方法无法确定方法体 不写方法体,声明为抽象方法

2,包含抽象父那个法的类,一定抽象类

3,抽象类不能直接实例化,创建对象

4,抽象类只能作为父类被继承

5,在继承抽象类型时候,必须重写与(实现)其抽象方法。

优点:

就限制了这个类的实例化,有些类如果能实例化,结果有害的

egTetromino就是不能被创建实例的类

可以创建它的子类型对象:T S L J...

abstract class Tetromino{....}

Tetromino本身是一个半成品,不应用new

在软件中,凡是泛化出的继承根,用于共享子类 公共部分的父类,应该说明为抽象类!

抽象方法:没有方法体的方法,由abstrct修饰

是子类方法的约定,是契约。

凡是要约定子类必须就有哪些方法,就可以通过定义抽象方法进行约定

 

接口:

接口可以看成是特殊的抽像类,即只包含有抽象方法的抽象类

接口中不可以定义成员变量,但可以定义常量

与继承不用,一个类可以实现多个接口,实现的接口直接用逗号隔开,

可以通过interface关键字来定义接口

interface Runner { 

    public static int DEFAULT_SPEED = 100

    public void run(); 

    接口就是一个标准,一个规范

    接口中只能包含常量和抽象方法

    接口不能被实例化

    接口子类的范围必须大于等于父类

    若类又继承父类又实现接口,需先继承后实现

    class Coo extends Abc implements IInter,IInter2 {//先继承后实现

   接口与接口之间可以继承

   interface IInter1{

double PI=.014159;

int NUM=5;//默认public static final

public abstract void shou();

void say();//默认public abstract

//int NUM2://常量必须同时声明初始化

}

接口与接口是继承关系,用extends继承

类与接口是实现关系,用implements实现

 

 

 

 


 

多态:

1,父类型引的子类实例,是多种多样的

2,执行子类型方法,执行结果松多种多样的

一个类型的引用在指向不同的对象时有不同的功能

同样一个对象,造型成不同类型时,具有不同的功能

父类型引用的对象可以是各种子类对象

同一个引用在对象不同的时候,调用的方法也不同

java语法规定:引用变量是什么类型,就只能在这个引用上访问那些方法,属性

1)java规定什么类型调用其声明的方法,和属性

2)如果当前类型变量没有对象声明方法利用强制转换型,将变量转换为包含方法的类型,就可以执行方法了

向上造型:

父类型变量(类,抽象类,接口)声明变量可以引用子类型实例

一个类的对象可以向上造型的类型有:

1,父类的类型

2,其实现的接口类型

能点出什么看类型

 

强制转型

子类小,父类大

实现类小,接口大

1,可以通过强制转换将父类型变量转换为子类型变量,前提是该变量指向的对象确实是该子类类型

2,也可以通过强制转换将变量装换为某种接口类型,前提是该变量指向的对象确实实现了该接口

关键字instanceof判断引用指向的对象是否为指定类型

boolean b1=f/*变量*/ instanceof Award/*类,接口*/;//false

强制转型本身不安全,如果先预测风险,没有风险再转换,有风险不转换,就安全了,先检查类型,如果类型是兼容的再进行转换就是安全的类型转换

经典写法:

if(f instanceof Award){

Award a=(Award)f:

System.out.println(a.getAwardType());

}

instanceoftrue两种情况

1)对象为该类型

2)对象实现了该接口

强制转型:两种情况

1)被转换的变量引用的对象,实现(继承)了目标类型,是目标类型的子类型,转换会成功

2)被转换的变量引用的对象,没有实现(继承)目标类型,不是目标类型的子类型,转换失败。抛出ClassCastException异常

 

强转时看对象

 

内部类

1,一个类可以定义在另外一个类的内部,定义在类内部的类称之为Inner,其所在的类称之为Outer

2Inner定义在Outer的内部,通常只服务于Outer类,对外部不具备可见型,Inner可以直接调用

outer的成员及方法(包含私有的)。

一般情况下,Inner对象会在Outer对象中创建(构造方法或者其他方法);Inner对象中会有

一个隐式的引用指向创建他的Outer类对象

内部类,一个类只被一个类使用,对外不可见

内部类对象通常只在外部类中被创建,内部类中可以直接访问外部类的所有成员

1,内部类只为外部类来使用,其他类不用

2,内部类可以直接访问外部类的所有成员,默认有个隐式的指向外部对象的Mama.this.

3,内部类通常只在外部类中被创建(new

 

匿名内部类

如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类)

而且对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。

1,何时用:有一个类(子类或实现类),只需创建一个对象,对象创建完,这个类就没有意义了

//不使用匿名内部类

interface Inter{

}

class Aoo implements Inter{

}

main(){

Aoo o=new Aoo():

}

//使用匿名内部类

interface Inter{

}

main(){

Inter o=new Inter(){实现类的成员};

}

匿名内部类优点:

1;封装:类的声明封装到方法中

2,简介:使用简练,经常用于继承类,抽象类实现接口,使用内部类

3,共享:外部对象的资源,可以共享方法中局部变量,java要求这个局部变量必须是final的缺点

不是完整功能:没有构造器重载!

 

 

小结:

面向对象3大特征:

1,封装:

类:封装数据,行为

作为一个整体操作

方法:封装功能的实现

隐藏实现的细节

访问修饰符:控制访问权限

保证数据的安全

2,继承:实现代码的重用

extends

3,多态:多种形态,在继承的基础之上

提高可维护型,可拓展型

1)一个类型指向不用的对象,有不用的实现

2)同一个对象造成不同类型,有不同功能

//for(int i=0;i<cells.length;i++){

//Cell c=cells[i];

//foreach循环,用途,简单替换上述代码

for(Cell c:cells){//等价于上两行,java1.5以上版本提供

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值