------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一、面向对象思想:
面向过程:关注步骤和过程
面向对象:关注的是对象面向对象是基于面向过程的
(1)类的定义
手机事物:属性: 品牌 , 颜色 , 价格 .....行为: 打电话 , 发短信 , 打游戏 ....手机类:成员变量: 品牌(brand) , 颜色(color) , 价格(price) 成员方法: 打电话(call) , 发短信(sendMessage) , 打游戏(playGame)
class Phone {
// 成员变量
String brand = "三星"; // 品牌
String color = "白色"; // 颜色
int price = 1999 ; // 价格
// 成员方法
// 打电话(call)
public void call(String name){
System.out.println("给" + name + "打电话");
}
// 发短信(sendMessage)
public void sendMessage(String name){
System.out.println("给" + name + "发短信");
}
// 打游戏(playGame)
public void playGame(){
System.out.println("玩游戏....");
}
}
(2)类与对象
我们学习编程的目的? 为了模拟现实生活中的事物 .
如何描述现实生活中的事物呢?
学生:
姓名,年龄, 性别 ....
学习 , 吃饭 , 睡觉 ....
属性: 就是事物的描述信息
行为: 就是该事物可以做什么事情
而我们java语言的最小单位是一个类. 所以我们就找到了事物是java语言中的一个东西的对应关系.
事物类
属性 成员变量
行为 成员方法
成员变量: 和之前定义变量一样,只不过位置不同,在类中方法外
成员方法: 和之前定义方法一样,只不过去掉static(后面在讲解)
类: 是一组相关属性和行为的集合, 类是一个抽象的东西
对象: 就是该类的一个具体体现
举例:
学生 类
班长 对象
使用类:
创建对象: 格式: 类名 对象名 = new 类名();
访问成员变量的格式: 对象名.变量名 ;
访问成员方法的格式: 对象名.方法名(...)
创建对象的步骤:
Student s = new Student();
步骤:
(1): 加载Student的字节码文件到方法区
(2): 在栈内存中为s开辟空间
(3): 在堆内存中为new Student()开辟空间
(4): 给成员变量进行默认初始化
(5): 给成员变量进行显式初始化
(6): 通过构造方法对成员变量赋值
(7): 将堆内存中的地址值赋值给栈内存中的引用变量s
(3)一个对象的内存图
(4)局部变量和成员变量的区别:
a: 在类中的位置不同
局部变量: 在方法定义中或者方法声明上的变量
成员变量: 在类中方法外
b: 在内存中的位置不同
成员变量: 在堆内存
局部变量: 在栈内存
c: 生命周期不同
成员变量: 随着对象的创建而产生,随着对象的消失而消失
局部变量: 随着方法的调用而产生,随着方法的消失而消失
d: 初始化值的问题:
成员变量: 有默认值(系统给定)
局部变量: 没有默认值,必须对其赋值以后才能使用
变量的注意事项:
a: 局部变量可以和成员变量的名称一致
b: 变量在访问的时候,遵循一个原则"就近原则"
(5)java语言中的参数传递问题:
基本数据类型的参数传递,形式参数的改变对实际参数没有影响
引用数据类型的参数传递,形式参数的改变对实际参数是有直接影响的
引用数据类型: 数组 , 类 , 接口
如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
class Demo {
public void show(int a){
System.out.println(a);
}
}
class Student {
public void method(){
System.out.println("student的method方法被调用了");
}
}
class StudentDemo {
// 以后在看到某一个方法上,需要一个类类型的变量.那么我们在调用的时候,需要传递的是一个该类的对象
public void function(Student s){ // Student s = new Student();
s.method();
}
}
// 测试类
class ArgsDemo {
public static void main(String[] args){
// 创建Demo对象
Demo d = new Demo();
// 调用方法
// int a = 20 ;
d.show(20);
System.out.println("----------------------------");
// 创建StudentDemo对象
StudentDemo sd = new StudentDemo();
// 创建Student对象
Student s = new Student();
sd.function(s);
}
}
(6)匿名对象: 就是没有名字的对象
匿名对象的作用:
a: 调用方法,仅仅调用一次的时候
b: 作为参数传递
class Student {
public void show(){
System.out.println("student的show方法被调用了");
}
}
class StudentDemo {
public void method(Student s){
s.show();
}
}
// 测试类
class NoNameDemo {
public static void main(String[] args){
// 创建Student对象
Student s = new Student();
// 调用show方法
s.show();
// s.show();
System.out.println("---------------------------");
// 匿名对象
// new Student();
new Student().show();
// new Student().show(); 重新创建了一个对象和之前不一样
System.out.println("---------------------------");
// 创建StudentDemo对象
// StudentDemo sd = new StudentDemo();
// 调用method方法
// sd.method(s);
// 把匿名对象作为参数传递
// sd.method(new Student());
new StudentDemo().method(new Student());
}
}
二、面向对象的3个特征:
封装
继承
多态
面向对象开发
就是不断的创建对象,使用对象,指挥对象做事情。
(1)封装
我们在赋值的时候,发现有时候可以为负数.但是我们都知道年龄不能为负数.所以我们应该对数据做一个校验吧.
我们需要将校验放在Student类中还是PrivateDemo类中?应该放在Student类中.为什么呢?
PrivateDemo 是一个测试类,既然是测试类,那么我们就需要测试所有的数据,而不能将错误的数据进行过滤吧.
校验: 我们需要使用一个逻辑的判断.所以我们需要使用语句.语句只能写在方法中,所以我们需要在Student类中
编写一个方法.(作用: 是给age设置值)
我们在使用的时候,我们还可以通过成员变量直接对其赋值.这样不太友好.
我们需要其强制的使用方法来对age设置.言下之意,就是不能让外界直接访问成员变量age.
这时候java就给我们提供了一个关键字: private (私有的)
封装的思想:
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装好处
隐藏实现细节,提供公共的访问方式
提高了代码的复用性
提高安全性。
封装原则
将不需要对外提供的内容都隐藏起来。
把属性隐藏,提供公共方法对其访问
a、private关键字的特点:
a: private是一个修饰符
b: 可以用来修饰成员变量和成员方法
c: 被private修饰的成员只能在本类中访问
// 学生类
class Student {
// 成员变量
String name ; // 姓名
private int age ; // 年龄
// 定义一个方法.作用: 是给age设置值
public void setAge(int a){
if(a > 120 || a < 0){
System.out.println("数据非法!!!");
}else {
age = a ;
}
}
// 成员方法
// 用来输出所有的成员变量
public void show(){
System.out.println(name);
System.out.println(age);
}
}
// 测试类型
class PrivateDemo {
public static void main(String[] args){
// 创建对象
Student s = new Student();
// 给成员变量赋值
s.name = "凤姐";
// s.age = 38 ;
s.setAge(38);
// 调用show方法
s.show();
System.out.println("-------------------------");
// 创建学生对象
Student s2 = new Student();
// 给成员变量赋值
s2.name = "刘亦菲";
// s2.age = -27 ;
s2.setAge(-27);
// 调用show方法
s2.show();
}
b、this关键字:
我们在起名字的时候,要做到的"见名知意",但是现在没有做到"见名知意",所以我们需要更改一下下.
this关键字: 代表的是本类对象的一个引用, 谁调用我this就代表谁.
this的存在解决的问题: 当局部变量将成员变量隐藏的时候,我们就可以通过this来明确直接访问的是成员变量.
变量在访问的时候遵循一个就近原则,现在我们的局部变量的名称和成员变量的名称一致.
所以在赋值的时候,并没有涉及到成员变量.
而我们的目的是: 把传递进来的name赋值为成员变量的name
我们访问成员变量只能通过对象来进行访问,那么谁有可以代表当前类的一个对象呢?
这时候java就给我们提供了一个关键字: this
c、构造方法
特点:
(1): 方法名和类名相同
(2): 没有返回值类型,连void也没有
(3): 没有返回值
作用:
给成员变量赋值
注意事项:
(1): 当我们没有给出构造方法的时候,系统将会提供一个默认的无参的构造方法
(2): 当我们给出构造方法的时候,系统将不会提供一个默认的无参的构造方法
d、static关键字
特点:
(1): 随着类的加载而加载
(2): 优先于对象存在
(3): 被类的所有的对象所共享
(4): 可以通过类名调用.本身也可以通过对象名调用
建议使用类名调用
注意事项:
(1): 在静态的方法中不能存在this关键字
(2): 静态只能访问静态
e、代码块
概述: 在java中使用{}括起来的内容
分类: 局部代码块 , 构造代码块 , 静态代码块 , 同步代码块(多线程)
局部代码块: 位置在方法定义中
构造代码块: 位置在类中方法外 , 特点: 每创建一次对象都调用一次 , 并且优先于构造方法执行
静态代码块: 位置在类中方法外 , 前面添加一个static 特点: 随着类的加载而加载,只执行一次 ,优先于构造代码块
(2)继承
格式:class 子类名 extends 父类名 {}
好处:
(1): 提高了代码的复用性
(2): 提高了代码的维护性
(3): 让类与类产生了关系,是多态的前提
弊端:
让类与类产生了关系,增强了耦合性
特点:
(1): 只能是单继承 ,不能是多继承
(2): 可以使用多层继承
注意事项:
(1): 父类中私有的成员不能被子类继承
(2): 父类中的构造方法不能被子类继承,但是可以通过super去访问
(3): 不能为了部分功能去使用继承
继承中成员变量的访问特点:
变量在访问的时候遵循一个"就近原则"
查找顺序:
(1): 在子类的局部位置
(2): 在子类成员位置
(3): 在父类的成员位置找
(4): 报错
this和super的区别:
this: 表示是本类对象的一个引用,谁调用我this就代表谁
super:表示的是父类存储空间的一个标识(理解: 父类对象的运用)
成员访问格式:
成员变量
this.变量名 本类的成员变量
super.变量名 父类的成员变量
构造方法
this(...) 本类的构造方法
super(...) 父类的构造方法
成员方法
this.方法名(...) 本类的成员方法
super.方法名(...)父类的成员方法
继承中构造方法的访问特点:
子类在初始化的时候,默认去调用父类的无参的构造方法
所有的构造方法的第一句都是super()
注意事项:
this(...) 和 super(...)必须是构造方法第一行
Object: 所有的类都是直接的或者间接的继承自该类
继承中成员方法的访问特点:
查找顺序:
(1): 在子类中查找
(2): 在父类中查找
(3): 报错
方法重写与方法重载的区别
方法重写: 子类中出现了和父类中一模一样的方法(方法名, 返回值类型 , 参数列表)
方法重载: 在同一个类中,允许同时存在一个以上的同名方法只要它们的参数列表不同, 与返回值无关
final关键字
特点:
final(最终的)
修饰类 被修饰的类不能被继承
修饰变量 被修饰的变量其实是一个常量
引用类型 指的是地址值不能被改变
基本类型 指定是值不能被改变
修饰方法 被修饰的方法不能被子类重写
final的初始化时机问题:
a: 只能被赋值一次
b: 在构造方法结束前赋上值就OK了(非静态的)
// 动物
class Animal {
// 成员变量
private String name ;
private int age ;
private String color ;
// 构造方法
public Animal(){}
public Animal(String name , int age , String color){
this.name = name ;
this.age = age ;
this.color = color ;
}
// 提供get和set方法
public void setName(String name){
this.name = name ;
}
public String getName(){
return name ;
}
public void setAge(int age){
this.age = age ;
}
public int getAge(){
return age ;
}
public void setColor(String color){
this.color = color ;
}
public String getColor(){
return color ;
}
// 成员方法: 吃饭 , 睡觉
public void eat(){
System.out.println("吃饭了....");
}
public void sleep(){
System.out.println("睡觉");
}
}
// 猫
class Cat extends Animal {
// 给出构造方法
public Cat(){}
public Cat(String name , int age , String color){
super(name , age , color);
}
// 抓老鼠
public void catchMouse(){
System.out.println("哦,抓到了一只老鼠...");
}
}
// 狗
class Dog extends Animal{
// 给出构造方法
public Dog(){}
public Dog(String name , int age , String color){
super(name , age , color);
}
// 看门
public void lookDoor(){
System.out.println("狗正在看门..");
}
}
// 测试类
class ExtendsTest3 {
public static void main(String[] args) {
// 创建一个狗对象
Dog d1 = new Dog();
// 给成员变量赋值
d1.setName("旺财");
d1.setAge(3);
d1.setColor("黄色");
// 输出成员变量
System.out.println(d1.getName() + "----" + d1.getAge() + "---" + d1.getColor());
System.out.println("-------------------------------");
// 创建对象
Dog d2 = new Dog("哮天犬" ,45 , "黑色" );
// 输出成员变量
System.out.println(d2.getName() + "----" + d2.getAge() + "---" + d2.getColor());
System.out.println("-------------------------------");
d2.eat();
d2.sleep();
d2.lookDoor();
}
}
(3)多态
前提:
(1): 需要有继承
(2): 需要有方法重写,没有方法重写也是可以的,但是没有意义
(3): 父类的引用指向子类对象
Fu f = new Zi();
多态中成员的访问特点:
成员变量: 编译看左边, 运行看左边
成员方法: 编译看左边 , 运行看右边
静态成员方法: 编译看左边 , 运行看左边
好处:
(1): 提供了代码的维护性(继承)
(2): 提供了代码的扩展性(多态)
弊端:
不能访问子类特有的功能
向下转型: 就是把父类的引用强制转换成子类的引用Zi zi = (Zi)f ;
向上转型: 父类的引用指向子类对象Fu f = new Zi();
抽象类
特点:
(1): 抽象类格式: abstract class 类名 {}
抽象方法的格式: public abstract 返回值类型 方法名(...);
(2): 抽象类中可以有非抽象方法,也可以有抽象方法,如果一个类中存在抽象方法,那么就需要将该类定义为抽象类
(3): 构造方法
有, 用于子类在访问数据的时候初始化
(4): 抽象类不能对其进行直接实例化,但是可以对其进行间接的实例化(多态的形式)
(5): 抽象类的子类
a: 可以是抽象类
b: 可以是具体的类,但是这个具体的类需要重写抽象类中的抽象方法
成员特点:
(1): 成员变量可以是变量,也可以是常量
(2): 构造方法有 , 用于子类在访问数据的时候初始化
(3): 成员方法可以是抽象方法,可以是非抽象方法
面试题:
abstract不能和那些关键字进行共存?
private冲突
final冲突
static无意义
接口
特点:
(1): 定义接口的格式 interface 接口名{}
(2): 类实现接口的格式 class 类名 implements 接口名{}
(3): 接口不能对其进行直接的实例化,但是可以通过多态的形式对其进行间接的实例化
(4): 接口的子类
a: 可以是抽象类
b: 可以是非抽象类,该类必须重写接口中的抽象方法
(5): 接口中没有构造方法,并且接口中的方法都是抽象方法
成员特点:
成员变量 只能常量,存在默认的修饰符public static final
构造方法 没有
成员方法 只能是抽象方法,存在默认的修饰符public abstract
类与类 , 类与接口, 接口和接口的关系
类与类: 继承关系(extends),只支持单继承,不支持多继承 , 但是可以多层继承
类与接口: 实现关系(implements) , 可以是单实现,也可以是多实现,并且一个类可以在继承一个类的同时,实现多个接口
接口和接口: 继承关系(extends),可以是单继承,也可以是多继承
抽象类和接口的区别:
a: 成员区别
抽象类
成员变量 可以是变量,也可以是常量
构造方法 有
成员方法 可以是抽象方法,也可以非抽象方法
接口
成员变量 只能是常量public static final
构造方法 没有
成员方法 只能是抽象方法public abstract
b: 关系区别
类与类: 继承关系(extends),只支持单继承,不支持多继承 , 但是可以多层继承
类与接口: 实现关系(implements) , 可以是单实现,也可以是多实现,并且一个类可以在继承一个类的同时,实现多个接口
接口和接口: 继承关系(extends),可以是单继承,也可以是多继承
c: 设计理念
抽象类 体现的是"is a"关系定义的都是该继承体系中共性的内容
接口 体现的是"like a"关系定义的都是该继承体系中扩展性的东西