1、类和对象
1.1 什么是对象:程序员眼中一切皆为对象
面向过程(C) VS 面向对象(java)
面向过程:
生活角度:亲力亲为做一件事
程序角度:main方法出发,直接执行操作
面向对象:
生活角度:找一个对象做事
程序角度:main方法出发,new对象,通过对象操作代码
案例:
面向过程---白白的皮肤,修长的腿
面向对象---佩奇(对象) 肤白,腿长
1.2 类和对象:
类: 一类事物的抽象化集合 例如:动物类,老师类, 学生类
对象:事物中具体的个体 例如:狗,猫, 老李, 梁欢
特征:帅,肤白-----程序中叫属性(名词)
行为:能吃,能睡---程序中叫方法(动词)
共性的抽取:某对象具体某种特征和行为,但其他对象也有(帅,肤白),所以设计时,需要抽取到类中
1.3面向对象的编程设计
创建一个类,类中有属性和方法,实例化对象,通过对象调属性和方法
class Student{ //创建一个类
//注意:类中的属性和方法是平级的
String name; //类中的姓名属性
int age; //类中的年龄属性
//类中的方法: 注意不要加static修饰
public void eat() {
System.out.println("很能吃");
}
}
public class OOP1 {
public static void main(String[] args) {
Student st = new Student(); //实例化对象
st.name = "张三"; //对象调属性
st.age = 18;
st.eat(); //对象调方法
}
}
1.4 实例化多个对象
//案例:张三同学很能吃,李四也很能吃
//分析: 类:学生类 对象: 张三 属性:姓名,年龄 方法:吃
//注意:在同一个包中,不能有同名的类
public class OOP2 {
public static void main(String[] args) {
Student st = new Student(); //实例化对象
//st.eat(); //成员属性没有赋值,则有默认值,String-null,int-0(和数组默认值类似)
st.name = "张三"; //对象调属性
st.age = 18;
//再实例化一个对象
Student st2 = new Student();
st2.name = "李四";
st.eat(); //对象调方法
st2.eat();
//结论: 实例化多个对象,每个对象都有独立的成员属性
}
}
2、成员变量与局部变量
a.出现位置:
成员变量:在类中,与成员方法平级
局部变量:方法体中
b.默认值问题:
成员变量:有默认值;String-null,int-0
局部变量:没有默认值;必须先赋值,再使用
c.作用域:
成员变量:至少在本类中
局部变量:方法体中,出了方法体,立即销毁
d.存储位置:(提前说明)
成员变量:在堆中
局部变量:在栈中
e.局部变量与成员变量重名:
重叠作用域中,作用域小的覆盖作用域大的--局部变量覆盖成员变量
案例:
//案例:创建学生类,属性有:姓名,年龄,性别,分数
//方法:打印信息 实例化多个对象去操作
class Student{
String name;
int age;
char sex;
double score;
public void sayHi() {
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
System.out.println("性别:"+sex);
System.out.println("分数:"+score);
}
}
public class OOP2 {
public static void main(String[] args) {
Student st1 = new Student();
st1.name = "张三";
st1.age = 19;
st1.sex = '男';
st1.score = 99;
Student st2 = new Student();
st2.name = "李四";
st2.age = 29;
st2.sex = '男';
st2.score = 98;
st1.sayHi();
st2.sayHi();
}
}
3.方法重载
方法重载:在同一个类中,方法名相同,参数类型或个数不同
案例:张三吃饭,吃药等
分析:属性:姓名 方法: 多种吃的方法 对象: new 对象 类: 男人类
系统识别重载方式:
系统调方法时,先看方法名是否相同;如果方法名相同,再看参数列表,根据参数类型和个数区分调哪个方法
重载好处:统一方法调用,屏蔽方法调用的差异化
注意:如果返回值类型不同,是否为重载?---不是
class Man{
String name;
//方法重载
public void eat(String rice) {
System.out.println(name+"正在吃"+rice);
}
public void eat(int fish) {
System.out.println(name+"正在吃"+fish+"条鱼");
}
public void eat(String rice,String yao) {
System.out.println(name+"先吃"+rice+";在吃"+yao);
}
/* 返回值类型不同,不是重载方法
public int eat(String yao) {
return 0;
}*/
}
public class Reload1 {
public static void main(String[] args) {
Man man = new Man();
man.name = "张三";
man.eat("大米饭");
man.eat(3);
man.eat("米饭", "药");
}
}
4.构造方法
概述:特殊的方法,和普通方法一样,有方法的调用和方法实现,只是结构不一样
4.1 无参数构造方法
构造方法调用: new 类名();
构造方法实现: 类名(){}
注意:
a.当我们没有写构造方法,系统自动产生构造方法实现
b.当我们写了构造方法,系统则不会自动产生构造方法实现
从面向对象案例出发,讲解构造方法
案例:女朋友帮忙洗衣服
分析: 类: 女朋友类 对象:我的女朋友 属性:姓名,年龄 方法:洗
构造方法的执行流程:
a.开辟空间 b.给成员属性赋初值 c.调用构造方法 d.将空间赋值给引用对象
class Girl{
String name; //属性
int age;
Girl(){ //构造方法实现: 类名(){}
System.out.println("调无参构造");
}
public void wash() { //方法
System.out.println(age+"岁的女朋友"+name+"正在帮忙洗衣服");
}
}
public class Contructor1 {
public static void main(String[] args) {
Girl girl = new Girl(); //构造方法调用
girl.name = "凤姐";
girl.age = 18;
girl.wash();
}
}
4.2 带参数构造方法
构造方法调用: new 类名("参数");
构造方法实现: 类名(数据类型 参数名){}
//从面向对象案例出发,讲解构造方法
//案例:小明正在睡觉
//分析: 类:Child 对象:小明 属性:姓名 方法:睡觉
class Child{
String name;
//构造方法的重载...
Child(){
System.out.println("无参构造...");
}
Child(String n){ //有参构造的实现
name = n;
}
public void sleep() {
System.out.println(name+"正在睡觉");
}
}
public class Contructor2 {
public static void main(String[] args) {
//1.无参构造
Child child = new Child();
child.name = "小明";
child.sleep();
//2.有参构造 = 无参构造+赋值
Child xm = new Child("小花");
xm.sleep();
}
}
5、this的用法
this概述:当前对象,谁调用this所在的方法,this就代表谁(此处代表xm)
5.1 this调属性
//案例:小明正在睡觉
//分析: 类:Child 对象:小明 属性:姓名 方法:睡觉
class Child{
String name;
//规范:往往带参构造的参数名和属性要一致
//问题:当参数名和属性名一致时,最终属性的结果为null
//原因:局部变量和成员变量重名问题,局部变量优先
//解决方案:this.成员属性
Child(String name){ //有参构造的实现
this.name = name;
}
public void sleep() { //name=null
System.out.println(name+"正在睡觉");
}
}
public class This1 {
public static void main(String[] args) {
//2.有参构造 = 无参构造+赋值
Child xm = new Child("小明");
xm.sleep();
}
}
5.2 this调方法
//this调方法:调当前对象的方法
//案例:小明能吃又能玩
class Person{
public void eat() {
System.out.println("小明正在吃");
//在成员方法(eat)中调另一个方法默认有this. 可以省略不写
this.play(); //当前对象调的play方法(谁调用this所在的方法,this就代表谁)
}
public void play() {
System.out.println("小明正在玩");
}
}
public class This2 {
public static void main(String[] args) {
Person person = new Person();
person.eat();
//person.play();
}
}
5.3 this调构造方法
//this调构造方法: this()-调无参构造, this(参数)-调带参构造
//案例: 小明有姓名,年龄,性别等属性,打印这些信息
//分析: 类: Student 方法: 打印信息
class Student{
String name;
int age;
char sex;
Student(){}
Student(String name,int age){
this.name = name;
this.age = age;
}
Student(String name,int age, char sex){
//1.this调构造方法必须出现在构造方法首句
//this(); //this调无参构造
this(name, age); //this调构造方法
this.sex = sex; //只需将新增的参数赋值到属性中即可
}
}
public class This3 {
public static void main(String[] args) {
Student st = new Student("小敏", 30, '女');
}
}
6、封装性
面向对象案例:小明在学习,属性有姓名,年龄
问题1:数据不合理,程序没问题 例如:age传入-3
处理:在main方法中传属性值时进行判断,默认18
问题2: main的冗余太多,需要封装
处理:在类中设置set方法进行封装;即规避了不合理数据,又提升了复用性
面向对象封装性的操作步骤:
1.属性私有化 (提升安全性)
2.通过set/get方法进行封装(提升复用性)
class Person{
String name;
private int age; //私有权限类,属性只能在当前类中使用
//set方法规范写法:set+属性名首字母大写,参数名和属性名一致
public void setAge(int age) {
//注意:后续的常用操作中,直接赋值即可,不用做判断了(此处为了安全性,做的判断)
if(age<0) {
this.age = 18; //默认18
}else {
this.age = age;
}
}
//get方法规范写法:get+属性名首字母大写 返回属性
public int getAge() {
return age;
}
public void work() {
System.out.println(age+"岁的"+name+"正在工作");
}
}
public class FengZhuang {
public static void main(String[] args) {
Person person = new Person();
person.name = "小明";
person.setAge(38);
//person.age = -3; //从源头数限制直接属性的赋值
person.work();
System.out.println(person.getAge()); //取属性值
}
}