1相关概念的理解
1.1面向过程、面向对象
面向过程与面向对象都是编程中,编写程序的一种思维方式。
面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程。(职员思想)
面向对象的程序设计方式,是遇到一件事时,思考“我该让谁来做”,然后那个“谁”就是对象,他要怎么做这件事是他自己的事,反正最后一群对象合力能把事就好就行了。(领导思想)
1.2面向对象思维方式的好处
面向对象思维方式是一种更符合人们思考习惯的思想
面向过程思维方式中更多的体现的是执行者(自己做事情),面向对象中更多的体现是指挥者(指挥对象做事情)。
面向对象思维方式将复杂的问题简单化。
2类与对象
2.1定义类
事物其实就是由特点(属性)和行为(功能)组成的。
通过计算机语言Java来描述这个事物,就是定义类,
定义类的格式:
public class 类名 {
//可编写0至n个属性
数据类型 变量名1;
数据类型 变量名2;
//可编写0至n个方法
修饰符 返回值类型 方法名(参数){
执行语句;
}
}
Tips:自定义类中:有main方法,其他方法就要加static,没有main,就不用加。
例:
public class Car { String color;//颜色 int tyre;//轮胎个数 //功能:跑 public void run(){ System.out.println("颜色为"+color+",轮胎个数为"+tyre+"的小汽车在跑"); }}
public class Test { public static void main(String[] args) { Car c=new Car(); c.color="红色"; c.tyre=4; c.run(); }}
2.2成员变量和成员方法
类的真正意义就是在描述事物。属性和功能统称为事物中的成员。
事物的成员分为两种:成员属性和成员功能。
成员属性在代码中的体现就是成员变量
成员功能在代码中的体现就是成员方法
2.3类和对象的区别
类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。
举例:
类是模型
对象是实体
设计时,是先有实体,再抽象出模型。
实际生产时,是先有模型,再有实体。
实际编程时,也是如此。
2.4局部变量和成员变量区别
1)定义的位置不同
成员变量定义在类中
局部变量定义在方法中或块(大扩号)中
例:
public class Student { String name; //成员变量 int age; //成员变量 String sex; //成员变量 public void study(String name){ //局部变量 int book=0; //局部变量 System.out.println("这个学生姓名为"+name+",年龄为"+age+",性别为"+sex); //这个name就成了局部变量,就近原则 System.out.println("这个学生读了"+book+"本书"); }}
2)在内存中的位置不同
成员变量存储在堆内存的对象中
局部变量存储在栈内存的方法中
3)生命周期不同
成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失
局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失
4)初始化不同
成员变量因为在堆内存中,所以有默认的初始化值
局部变量没有默认的初始化值,必须手动的给其赋值才可以使用
2.5基本类型和引用类型作为参数传递
例:
public class Test2 { public static void main(String[] args) { int a=1; double b=2; method1(a,b); System.out.println(a); System.out.println(b); } public static void method1(int a,double b){ a=20; b=30; }}
public class Test3 { public static void main(String[] args) { Student s=new Student(); s.name="同学1"; s.age=38; s.sex="男"; method1(s); s.study(); } public static void method1(Student s){ s.name="同学2"; s.age=18; s.sex="男"; }}
当引用变量作为参数传递时,这时其实是将引用变量空间中的内存地址(引用)复制了一份传递给了method1方法的s引用变量。这时会有两个引用同时指向堆中的同一个对象。当执行method1方法中的s.name="同学2"时,会根据s所持有的引用找到堆中的对象,并将其s属性的值改为同学2,method1方法弹栈。
由于是两个引用指向同一个对象,不管是哪一个引用改变了引用的所指向的对象的中的值,其他引用再次使用都是改变后的值。
3封装
面向对象三大特征:封装,继承,多态
封装的概念:隐藏了实现细节,还要对外提供可以访问的方式
3.1封装表现
1)方法就是一个最基本封装体。
2)类也是一个封装体。
3.2封装的好处
1)提高了代码的复用性。
2)隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。这是核心之一,也可以理解为就是封装的概念。
3)提高了安全性。
封装举例:机箱
3.3私有private
举例:定义一个Person类
Public class Person { String name; int age;}
public class Test { public static void main(String[] args) { Person p1=new Person(); p1.name="小红帽"; p1.age=-100; //不安全因素 System.out.println(p1.name); System.out.println(p1.age); }}
通过上述代码发现,虽然用Java代码把Person描述清楚了,但有个严重的问题,就是Person中的属性的行为可以任意访问和使用。这明显不符合实际需求(如代码中年龄为负值)。
解决办法:需要使用一个Java中的关键字也是一个修饰符 private(私有,权限修饰符)。只要将Person的属性和行为私有起来,这样就无法直接访问:
public class Person { private String name; private int age;}
这时,Test类中访问不到了:
然后在Person类中提供对外访问接口:
public class Person { private String name; private int age; //赋值方法 public void setName(String n){ name=n; } public void setAge(int a){ if(a>=0&&a<=200){ age=a; }else{ age=0; } } //取值方法 public String getName(){ return name; } public int getAge(){ return age; } }
在Test中:
public class Test { public static void main(String[] args) { Person p1=new Person(); p1.setName("小红帽"); p1.setAge(-100); System.out.println(p1.getName()); System.out.println(p1.getAge()); }}
总结:
类中不需要对外提供的内容都私有化,包括属性和方法。
以后再描述事物,属性都私有化,并提供setXxx,getXxx方法对其进行访问。
注意:私有仅仅是封装的体现形式而已。
在eclipse中有可以自动添加这两个方法的功能:
建好成员变量(并私有)后,在代码区右键-- Source-- Generate Getters and Setters
选择上变量,就会自动建好了:
3.4 this关键字
3.4.1成员变量和局部变量同名问题
可以在成员变量名前面加上this.来区别成员变量和局部变量。
3.2.2 this代表本类对象
具体代表哪个对象:
哪个对象调用了this所在的方法,this就代表哪个对象。
例:比较年龄
public class Person { private String name; private int age; //赋值方法 public void setName(String n){ name=n; } public void setAge(int a){ if(a>=0&&a<=200){ age=a; }else{ age=0; } } //取值方法 public String getName(){ return name; } public int getAge(){ return age; } //判断是否同龄人 public boolean compare(Person p){ //传入一个对象 return this.age==p.age; } }
public class CompareAge { public static void main(String[] args) { Person p1=new Person(); p1.setName("张"); p1.setAge(18); Person p2=new Person(); p2.setName("赵"); p2.setAge(18); boolean flag=p1.compare(p2); System.out.println(flag); }}
3.4.3内存解释
4 继承
继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。
4.1继承的格式和使用
class 子类 extends 父类 {}
先有父类,再有子类
分析时,是先有子类,再抽象出父类
例:
//员工(父类)public class Emp { String name; int age; public void work(){ System.out.println(name+"员工正在工作"); }}
//研发部员工继承自员工public class Rcenter extends Emp {}
//维护部员工继承自员工public class Mcenter extends Emp{ //子类独有方法 public void speak(){ System.out.println("我叫"+name); }}
//测试public class Test { public static void main(String[] args) { Rcenter r=new Rcenter(); r.name="小猪"; r.age=18; System.out.println(r.name); System.out.println(r.age); r.work(); Mcenter m=new Mcenter(); m.name="小狗"; m.age=17; m.work(); m.speak(); }}
4.2继承的好处
1)继承的出现提高了代码的复用性,提高软件开发效率。
2)继承的出现让类与类之间产生了关系,提供了多态的前提。
4.3继承中注意事项
1)类只支持单继承,不允许多继承。也就是说一个类只能有一个直接父类(人只能有一个亲生父亲)
class A{}
class B{}
class C extends A,B{} // 错误:C类不可以同时继承A类和B类
2)多个类可以继承一个父类(父亲可以有多个儿子)
class A{}
class B extends A{}
class C extends A{} // 类B和类C都可以继承类A
3)多层继承是可以的,即一个类的父类可以再去继承另外的父类(祖父,父,儿子)
class A{}
class B extends A{} // 类B继承类A,类B是类A的子类
class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类
4)子类和父类是一种相对概念。一个类是某个类父类的同时,也可以是另一个类的子类。
4.4成员变量、成员方法的变化
1)如果子类父类中出现不同名的成员变量,这时的访问是没有任何问题
2)父类中的成员变量是非私有的,子类中可以直接访问,若父类中的成员变量私有了,子类是不能直接访问的
3)当父类和子类中有相同的成员变量时,自己有,用自己的,自己没有,用父类的。(就近原则)
4)当子父类中出现了同名成员变量时,在子类中若要访问父类中的成员变量,必须使用关键字super来完成。super用来表示当前对象中包含的父类对象空间的引用。
Super表示父类对象(super只能子类用)
格式:super.父类中的成员变量
例:
public class Fu { int a=1; }
public class Zi extends Fu{ int a=2; public void method(){ int a=3; System.out.println("a="+a); System.out.println("a="+this.a); System.out.println("a="+super.a); }}
public class Test { public static void main(String[] args) { Zi z=new Zi(); System.out.println("a="+z.a); z.method(); }}
5)若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。
4.5方法重写(覆盖)
4.5.1概念
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖。
例:
public class Fu { public void show(){ System.out.println("这是父类方法"); }}
public class Zi extends Fu{ //方法重写 public void show(){ System.out.println("这是子类方法"); }}
public class Test { public static void main(String[] args) { Zi z=new Zi(); z.show(); } }
4.5.2方法重写(覆盖)的应用
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
在子类中,访问父类中的成员方法格式:
super.父类中的成员方法();
例:
public class Phone { public void show(){ System.out.println("显示电话号码"); } public void sendM(){ System.out.println("发短信"); } public void call(){ System.out.println("打电话"); } }
public class Iphone extends Phone{ public void show(){ super.show(); //父类方法 System.out.println("显示姓名"); System.out.println("显示头像"); }}
public class Test { public static void main(String[] args) { Iphone i=new Iphone(); i.show(); i.sendM(); i.call(); }}
4.5.3方法重写注意事项
1)子类方法覆盖父类方法,必须要保证权限大于等于父类权限(修饰符 default或不写小于public,以后会再学)。
class Fu(){ void show(){} public void method(){}}class Zi extends Fu{ public void show(){} //编译运行没问题 void method(){} //编译错误}
2)写法上注意:必须一模一样:方法的返回值类型 方法名 参数列表都要一样
3)必须有父类,才有方法重写的概念
对比记忆:方法重载:在同一个类中,方法名相同,参数列表的顺序、数量、类型不同(有一个就可以),返回值无所谓。
练习1:
项目经理类
属性:姓名 工号 工资 奖金
行为:工作work(打印姓名、工号、工资、奖金)
程序员类
属性:姓名 工号 工资
行为:工作work(打印姓名、工号、工资)
练习2:
已知学生类和老师类如下:
属性:姓名,年龄
行为:吃饭
老师有特有的方法:讲课
学生有特有的方法:学习
练习3:
已知猫类和狗类:
属性:毛的颜色,腿的个数
行为:吃饭
猫特有行为:抓老鼠catchMouse
狗特有行为:看家lookHome