一、面向对象
1、面向过程:强调的是过程(动作)更好理解的说是C语言中的函数
eg:吃土豆
①去菜市场
②买土豆
③做土豆
2、面向对象:强调的是对象(实体)
eg:吃土豆 把土豆都带回家,吃
面向对象和面向过程的对比
面向对象的特点:
1.将复杂的问题简单化
2.让曾经在过程中的执行者,变成了对象的指挥者
用面向对象的特征:封装,继承,多态
二、类与对象
1、类:对生活中的事物进行描述,用属性和行为描述
只要明确事物的属性和行为并定义在类中即可
2、对象:其实就是该类事物实实在在存在的个体
3、类与对象的关系:
类:事物的描述
对象:该类事物的实例。在Java中通过new 来创建的
4、成员:事物中的组成部分
成员变量<——>行为
成员函数<——>属性
5、类与对象的应用
描述小汽车:
class Car
{
int num; //小汽车轮胎数 成员变量
//默认num初始化值为0 若给num赋值则为显示初始化
String color; //小汽车颜色
void run() //成员函数 调用方法时方法要先进栈
{
System.out.println(num+"....."+color);
}
}
class CarDemo
{
public static void main(String[] args)
{
//在计算机中创建一个car的实例,通过new关键字
Car c = new Car(); //Car是类,c是类类型的引用变量,指向了该类的对象
c.num = 4;
c.color = "red";
c.run(); //要使用对象中的内容可以通过 对象.成员的形式来完成调用。
}
}
运行结果
6、成员变量和局部变量的区别
a)成员变量定义在类中,整个类都可以访问。
局部变量定义在函数,语句,局部代码块中,只有所在所属区域有效。
b)成员变量存在于堆内存的对象中。
局部变量存在于栈内存的方法中。
c)成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
d)成员变量都有默认初始化值。
局部变量没有默认初始化值。
6、类类型参数
类类型的变量肯定指向对象,要不就是空(null)
类类型参数的应用
7、匿名对象
没有名字的对象 new Car();
其实就是定义对象的简写格式
使用方式
eg:
1、Car c = new Car();
c.run();
写成匿名对象的格式为
new Car().run();
2、CarDome c1=new CarDome();
show(c1);
写成匿名对象的格式为
show(new Car());
所以!
1、当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。
2、匿名对象可以作为实际参数进行传递。
三、封装
封装: 隐藏对象的属性和实现细节,仅对外提供公共访问方式。
优点:
提高安全性
将变化隔离
提高了多次使用性
封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏起来,提供公共方法对其访问
举个栗子!
人的属性封装private:私有,是一个权限修饰符。用于修饰成员。私有的内容只在本类中有效。
四、构造函数
1、构造函数
特点
- 函数名与类名一致
- 不用定义返回值值类型
- 没有具体返回值
作用
- 给对象进行初始化
来!再举个栗子
class Person
{
private String name;
private int age;
//定义一个Person类的构造函数。
Person() //构造函数,而且是空参数
{
System.out.println("person run");
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
}
}
代码及运行结果
2、默认构造函数:
构造函数:构建创造对象时调用的函数,创建对象都必须通过构造函数初始化
一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数。eg:
class Person
{
Person(){}
}
如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。
3、一般函数和构造函数的区别
- 构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。会调用只调用一次。
eg:
public static void main(String[] args)
{
Person p = new Person();
}- 一般函数:对象创建后,需要函数功能时才能调用。可以被多次调用。
eg:
public static void main(String[] args)
{
Person p = new Person();
p.speak();
p.spesk();
}
4、构造函数—重载
定义构造函数:
在描述事物时,该事物已存在就具备的一些内容,这些内容都定义在构造函数中。
class Person
{
private String name;
private int age;
//定义一个Person类的构造函数。
Person() //构造函数,而且是空参数
{
name = "baby";
age = 1;
System.out.println("person run");
}
Person(String n) //一个参数的构造函数
{
name=n;
}
Person(String n,int a) //两个参数的构造函数
{
name=n;
age=a;
}
public void speak()
{
System.out.println(name+":"+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.speak();
Person p1=new Person("乐乐");
p1.speak();
Person p2 = new Person("小乐乐",20);
p2.speak();
}
}
运行结果
重载
多个构造函数在一个类中出现,他们的存在形式就叫做重载
构造函数有多个,用于对不同的对象进行针对性的初始化。多个构造函数在类中是以重载的形式体现的。
五、继承
1、继承概念:
举个栗子说明:
原始方法
找出二者共性,利用继承,减少代码数量
继承方式
继承的好处:
- 提高了代码的复用性
- 让类与类之间产生了关系,给多态提供了前提(没有继承就没有多态)
2、继承方式
- 单继承:一个子类只能有一个直接父类
- 多继承:一个子类可以有多个直接父类(Java中不允许,会产生调用的
不确定性) - 多层(多重)继承:就会出现继承体系
举个栗子说明:D继承了C,C继承了B,B继承了A。A是这个继承体系里最基础的;创建D对象是功能最全的
所以通过例子可知:
要使用继承体系
①查看该体系中的顶层类,了解该体系的基本功能
②创建体系中的最子类对象,完成功能的使用。
3、定义继承
当类与类之间存在着所属关系的时候,就定义继承。
简单来说:xxx是yyy中的一种。xxx extends yyy。
4、子父类中成员变量的特点
体现在:
- 成员变量
- 成员函数
- 构造函数
①成员变量
class Fu //成员变量
{
int num1 = 4;
}
class Zi extends Fu
{
int num2 = 5;
void show()
{
System.out.println(num2+"...."+num1);
}
}
class ExtendsDemo2
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show();
}
}
成员变量运行结果
当本类的成员和局部变量同名时用this区分(简单来是this代表本类对象的引用)
当子父类中的成员变量同名用super区分父类(简单来说super代表一个父类空间)
②成员函数
class Fu //成员函数
{
void show1()
{
System.out.println("fu show run");
}
}
class Zi extends Fu
{
void show2()
{
System.out.println("zi show run");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Zi z = new Zi();
z.show1();
z.show2();
}
}
成员函数运行结果
当子父类中出现成员函数一摸一样的情况,会运行子类的函数。
这种现象叫做覆盖
因此会出现函数的两个特性:
- 重载(overload):同一个类中
- 覆盖(overide):在子类中。覆盖也称为重写,覆写。
5、覆盖
-
子类方法覆盖父类方法时,子类权限必须大于等于父类权限。
eg:
覆盖权限 -
静态只能覆盖静态,或被静态覆盖(不常用,不作解释)
覆盖的应用
当对一个类进行子类的拓展时,子类要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就使用覆盖操作。
举个栗子说明:
使用手机:以前只能接电话,现在可以看到头像,名字。。
运行结果及代码
6、子父类中构造函数的特点
举个栗子好判断
在子类构造对象时,访问子类构造函数时,父类也运行了:见下图咯
访问子类构造函数
原因是:在子类的构造函数中第一行有一个默认的隐式语句。super();
出现父类函数的原因
由上,就出现了子类的实例化过程:
子类中所有的构造函数默认都会访问父类中的空参数的构造函数。
那么,为什么呢?
是因为子类继承了父类,获取了父类中内容(属性),所以在使用父类内容之前,要先看父类是如何对自己的内容进行初始化的。
所以子类在构造对象时,必须访问父类中的构造函数。
如果父类中没有定义空参数的构造函数,那么子类的构造函数必须用super明确调用父类中的哪个构造函数。同时子类构造函数中如果使用了this. 调用了本类构造函数时,那么super就没有了,因为super和this都只能定义第一行,所以只能有一个。
但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。
ps:super语句必须要定义在子类的构造函数的第一行,因为父类的初始化动作要先完成。
(不能用this. 会死循环哟!)
六、多态
某一事物的多种存在形态。 eg:函数
1、对象的多态性
举个栗子来说明什么是对象的多态性
形象说明什么是对象的多态总的来说:就是一个对象对应着不同形态
多态在代码中的体现:
父类或者接口(后面会说)的引用指向其子类对象。
上面形象的案例拿代码说话!
abstract class Animal
{
abstract void eat();
}
class Dog extends Animal
{
void eat()
{
System.out.println("啃骨头");
}
void lookHome()
{
System.out.println("看家");
}
}
class Cat extends Animal
{
void eat()
{
System.out.println("吃鱼");
}
void catchMouse()
{
System.out.println("抓老鼠");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Cat c = new Cat();
Dog d = new Dog();
method(c);
method(d);
method(new Cat());
}
public static void method(Animal a) //Animal a = new Dog();
{
a.eat();
}
}
运行结果
由此可以看出:找出一类物种所具有的共性就可以利用多态
多态的好处
提高了代码的扩展性,前期定义的代码可以使用后期的内容
多态的弊端
前期定义的内容不能使用(调用)后期子类的特有内容
多态的前提
①必须有关系,继承,实现
②要有覆盖
2、多态的转型
还是上面的栗子,其他不动,改变主函数
class DuoTaiDemo
{
public static void main(String[] args)
{
Animal a = new Cat(); //自动类型提升,猫对象提升为了动物类型,但是特有功能无法访问。
//作用就是限制对特有功能的访问
a.eat();
//如果你还想用具体动物猫的特有功能
//你可以将该对象进行向下转型。
Cat c = (Cat)a; //向下转型的目的是为了使用子类中的特有方法。
c.eat();
c.catchMouse();
}
}
运行结果
对于转型,自始自终都是子类对象在做着类型的变化!
3、多态的对象类型判断
目的:通常再向下转型的时候判断用——增强代码的健壮性!
还是最上面的栗子,其他不动,改变主函数
class DuoTaiDemo
{
public static void main(String[] args)
{
Animal a = new Cat();
method(a);
}
public static void method(Animal a)
{
a.eat();
if(a instanceof Cat) //instanceof:用于判断对象的具体类型
//只能用于引用数据类型判断
{
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog d =(Dog)a;
d.lookHome();
}
}
}
运行结果
4、多态的成员特点
- 成员函数(非静态)
编译时:参考引用型变量所属的类中是否有调用的函数,有:编译通过;没有,编译失败。
向上转型。将子类型隐藏,就不用子类的特有方法。
运行时:参考的是对象所属类中是否有调用的函数
简单说:编译看左边,运行看右边。
子父类成员函数都存在时
只有父类函数时
子父类都没有成员函数——肯定编译失败呀!还用问么
- 成员变量
编译时:参考引用型变量所属的类中是否有调用的成员变量,有:编译通过;没有,编译失败。
运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量
简单的说:编译和运行都参考等号的左边
上图!
当子父都有成员变量时
子类没有成员变量,父类有成员变量时
当子父都没有成员变量时
- 静态函数
编译时:参考引用型变量所属的类中是否有调用的静态方法
编译时:参考引用型变量所属的类中是否有调用的静态方法
简单说:编译运行都看左边。
其实对于静态方法,是不需要对象的。直接用类名调用即可。
运行解说
好!完美!收工!(欢迎找茬!)
网友评论