1.对象(object):万事万物皆对象
指具体的一个事物,具体的实体,占空间
对象从属性和方法两个方面进行描述
1)属性:指对象的特征(静态的)
2)方法:指对象的动作或功能(动态的)
2.类(class)
是具体相同或相似性质的对象的抽象
描述的是一类事物,类也有属性和方法
类是抽象的概念,不占空间
3.实际编程流程
先写类
创建类:写属性和方法
再创建对象:(main方法)
创建对象的格式:类名 对象名 = new 类名( );
访问属性:对象名.属性
调用方法:对象名.方法名( );
1 public class Dog { 2 /* 3 * 狗: 4 * 属性:品种、颜色、年龄、名字 5 * 方法:(跑、叫),输出基本信息 6 */ 7 //属性 8 String type; 9 String color; 10 int age; 11 String name; 12 //方法 13 public void info () { 14 System.out.println("这是一只" + color +"的" + type); 15 System.out.println("叫" + name +"今年" + age + "岁了"); 16 } 17 }
1 public class TestDog { 2 public static void main (String[] args) { 3 //创建对象 4 Dog d1 = new Dog(); 5 //赋值 6 d1.age = 5; 7 d1.color = "灰色"; 8 d1.name = "小白"; 9 d1.type = "长毛犬"; 10 //调用 11 d1.info(); 12 } 13 }
terminal终端运行结果:
4.变量的作用域
变量可以使用作用域(空间,由声明的位置决定)和生存期来衡量
作用域:
- 成员变量:直接声明在类中(类的属性),在该类中都可以使用
- 局部变量:声明在某个方法或语句块内,只有在该方法或语句块内可以使用
注意:局部变量和成员变量重名,则采用就近原则
5.方法的调用
如果a( )要调用b( )方法
1)如果在同一个类中,直接调用
public void a ( ) { ...... b(); ...... }
2)如果不在同一个类,必须先创建b( )所在的类的对象,然后对象名.b( )
public void a ( ) { ...... Bird b1 = new bird(); b1.b(); ...... }
面向对象的优点
- 便于模拟现实世界
- 隐藏细节
- 有利于代码的重用
6.基本类型和引用类型的区别
基本类型 | 引用类型 |
存储单个数据 | 复合类型的,存储多个数据,并且还有方法 |
创建:int a; | 必须用new分配内存: Dog d1 = new dog( ) |
使用:a = 5; | 对象名.属性 对象名.方法( ) |
内存:存储在栈区 | 引用在栈区,实际数据在堆区 |
必须先赋值才能使用 | 系统会自动初始化(本类型的0值) |
7.面向对象的主要特征:封装、继承、多态
一、属性的封装(隐藏,整体)
方法:语句块的封装
类:属性和方法的封装
1.访问修饰符
private:私有的,只有本类可以访问
默认的(default):只有本包内的类可以访问
public:公有的,该项目的类都可以访问
protected:保护的,只有本包的类和它的子类可以访问
2.this:表示本对象的
作用:
区分成员变量和局部变量。用this.调用的都是成员变量
在构造方法中,调用本类其他的构造方法,格式:this(实参); 注意:该句必须位于第一句
3.属性封装的步骤:
- 将属性私有化
- 给属性提供公有的get和set方法
- 如果对值得范围有限制,在set方法中限制
优点:可以灵活的控制属性的读,写,隐藏数据,更安全
创建一个Teacher对象:
1 public class Teacher { 2 /* 3 * 属性:姓名、年龄、教授课程 4 * 方法:自我介绍、讲课 5 */ 6 private String name; 7 private int age; 8 private String lesson; 9 //构造方法 10 public Teacher(String name,int age,String lesson){ 11 this.setName(name); 12 this.setAge(age); 13 this.setLesson(lesson); 14 System.out.println("Teacher(name,age,lesson)被调用!"); 15 } 16 public Teacher(String name,String lesson){ 17 this.name = name; 18 this.lesson = lesson; 19 this.age = 20; 20 System.out.println("Teacher(name,lesson)被调用!"); 21 } 22 public Teacher(){ 23 // this.name="无名"; 24 // this.lesson="不详"; 25 // this.age=30; 26 System.out.println("Teacher()被调用!"); 27 } 28 public void introduce(){ 29 System.out.println(name+"老师今年"+age+"岁,教授"+lesson); 30 } 31 public void teach(){ 32 System.out.println(name + "老师正在教" + lesson + "课程"); 33 } 34 public void teach(int n){ 35 System.out.println(name+"老师正在讲"+lesson+"课程的第"+n+"章内容。。。"); 36 } 37 public void teach(String text){ 38 System.out.println(name+"老师正在讲"+lesson+"课程的"+text+"部分的内容。。。"); 39 } 40 public String getName() { 41 return name; 42 } 43 44 public void setName(String name) { 45 this.name = name; 46 } 47 48 public int getAge() { 49 return age; 50 } 51 52 public void setAge(int age) { 53 this.age = age; 54 } 55 56 public String getLesson() { 57 return lesson; 58 } 59 60 public void setLesson(String lesson) { 61 this.lesson = lesson; 62 } 63 }
接着创建测试类进行测试:
1 public class test { 2 public static void main(String args[]){ 3 Teacher t1=new Teacher(); 4 t1.setName("姚明"); 5 t1.setAge(40); 6 t1.setLesson("篮球"); 7 8 t1.introduce(); 9 t1.teach(); 10 } 11 }
此时调用Teacher( )
调用Teacher(name,age,lesson)
1 public class test { 2 public static void main(String args[]){ 3 4 Teacher t2=new Teacher("李白",50,"诗歌"); 5 t2.introduce(); 6 } 7 }
调用Teacher(name,lesson)
1 public class test { 2 public static void main(String args[]){ 3 4 Teacher t3=new Teacher("张三丰","武术"); 5 t3.introduce(); 6 } 7 }
调用teach( )
1 public class test { 2 public static void main(String args[]){ 3 4 Teacher t3=new Teacher("张三丰","武术"); 5 6 t3.teach(); 7 } 8 }
调用teach(int n)
1 public class test { 2 public static void main(String args[]){ 3 4 Teacher t3=new Teacher("张三丰","武术"); 5 t3.teach(4); 6 } 7 }
调用teach(String text)
1 public class test { 2 public static void main(String args[]){ 3 4 Teacher t3=new Teacher("张三丰","武术"); 5 6 t3.teach("太极拳"); 7 } 8 }
其他:
1 public class test { 2 public static void main(String args[]){ 3 Teacher t1=new Teacher(); 4 //t1.setAge(40); 5 6 int age=t1.getAge(); 7 age++; 8 t1.setAge(age); 9 System.out.println("现在的年龄:"+t1.getAge()); 10 } 11 }
test测试类中的不调用,Teacher对象中的也不调用,则结果为1,如图
调用Teaher对象,测试类中的不调用,则输出为31
Teacher对象和测试类中的都调用,则输出41
1 public class test { 2 public static void main(String args[]){ 3 Teacher t1=new Teacher(); 4 t1.setAge(40); 5 6 int age=t1.getAge(); 7 age++; 8 t1.setAge(age); 9 System.out.println("现在的年龄:"+t1.getAge()); 10 } 11 }
二、构造方法(constructor)
1.作用:负责对象成员的初始化工作(给属性赋值)
2.语法:与类同名,没有返回值类型的方法
3.什么时候调用:创建对象时,用new关键字调用
4.注意:
- 如果类中没有自定义的构造方法,系统会自动添加一个默认的无参的构造方法;如果类中有自定义的构造方法,系统就不在添加
- 构造方法可以重载(不能被继承,不能被重写)
方法重载:overloading,在同一个类中,方法名相同,参数列表不相同
5.实例代码块
直接放在类中的用{ }起来的代码,也是用来做初始化工作
1 public class Book { 2 /* 3 * 1. 编写一个类Book,代表教材: 4 具有属性:名称(title)、页数(pageNum)(页数要求不少于200页)、种类(type) 5 具有方法:detail,用来在控制台输出每本教材的名称、页数、种类 6 具有两个带参构造方法:第一个构造方法中,设置教材种类为“计算机”(固定),其余属性的值由参数给定; 7 第二个构造方法中,所有属性的值都由参数给定 8 9 编写测试类BookTest进行测试: 10 分别以两种方式完成对两个Book对象的初始化工作,并分别调用它们的detail方法,看看输出是否正确 11 */ 12 //属性 13 private String title; 14 private int pageNum = 90; 15 private String type; 16 //构造方法 17 public Book(String title, int pageNum, String type) { 18 this.title = title; 19 this.setPageNum(pageNum); 20 this.type = type; 21 System.out.println("构造方法被调用"); 22 } 23 // 24 public Book(String title,String type){ 25 this.title = title; 26 this.setPageNum(pageNum); 27 this.type = type; 28 } 29 // 30 public Book (){ 31 this("a",0,"a"); 32 } 33 //实例代码块 34 { 35 System.out.println("实例代码块"); 36 } 37 //方法 38 public void detail () { 39 System.out.println(title + "共" + pageNum + "页,属于" + type); 40 } 41 42 public String getTitle() { 43 return title; 44 } 45 46 public void setTitle(String title) { 47 this.title = title; 48 } 49 50 public int getPageNum() { 51 return pageNum; 52 } 53 54 public void setPageNum(int pageNum) { 55 if(pageNum < 200){ 56 System.out.println("页数不能少于200页"); 57 }else{ 58 this.pageNum = pageNum; 59 } 60 } 61 62 public String getType() { 63 return type; 64 } 65 66 public void setType(String type) { 67 this.type = type; 68 } 69 }
编写测试类测试:
1 public class Test { 2 public static void main(String args[]){ 3 // 4 Book b1 = new Book(); 5 6 b1.setTitle("红楼梦"); 7 b1.setPageNum(500); 8 b1.setType("文学"); 9 b1.detail(); 10 } 11 }
结果为:
测试类中:Book b1 = new Book();此时回到
public Book (){
this("a",0,"a");
}
在回到构造方法中,所以会输出图中“页面不能少于200页”和“构造方法被调用”
如果在测试类中直接加参数,则直接回到构造方法中进行输出:
1 public class Test { 2 public static void main(String args[]){ 3 4 Book b2=new Book("三国演义",600,"古典文学"); 5 } 6 }
若只给title和type,则调用上面Book类中的第二个构造方法:
1 public class Test { 2 public static void main(String args[]){ 3 4 Book b3=new Book("疯狂java","计算机"); 5 b3.detail(); 6 } 7 }
若将属性中的pageNum改为大于200的数,则不会输出“页数不能少于200页”,如图:
三、继承
1.继承(inherit):从一个类出发生成另外一个类的过程
父类:super class 超类,based class 基类
子类:subclass,派生类或导出类或衍生类 derived class
2.继承的关键字:extends
3.继承需要注意的问题:
子类是否可以继承父类所有的成员?
私有的成员可以继承到,但是不能直接访问
访问修饰符:都可以继承,不能直接访问
构造方法
创建子类对象时,默认调用父类无参的构造方法。
如果父类没有无参的构造方法或要调用父类带参的构造方法,必须用super关键字显式调用,格式:super(实参);注意:必须位于第一句
一个类只能有一个父类(java继承的单根性,单继承)
所有类的根类:java.lang.Object
子类可以重写父类的方法
4.方法重写:overriding(方法覆盖)
在子类中存在与父类中方法名,参数列表,返回值类型完全一致的方法,这时就称子类重写了父类的方法。要求:访问范围不能缩小
5.优点:可以有效的实现代码重用
实例一:
Person,Student,Teacher,Test Student和Teacher继承Person,代码如下:
Person:
1 public class Person { 2 //属性 3 private String name; 4 private char sex; 5 private int age; 6 //构造方法 7 public Person(String name, char sex, int age) { 8 this.name = name; 9 this.sex = sex; 10 this.age = age; 11 } 12 13 //方法 14 public void introduce(){ 15 System.out.println(name + "," + sex + "今年" + age + "岁。"); 16 } 17 //get和set方法 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 public char getSex() { 27 return sex; 28 } 29 30 public void setSex(char sex) { 31 this.sex = sex; 32 } 33 34 public int getAge() { 35 return age; 36 } 37 38 public void setAge(int age) { 39 this.age = age; 40 } 41 }
Student:
1 public class Student extends Person { 2 3 private int num; 4 5 //构造方法(继承了Person所以也有name,sex,age属性) 6 public Student(String name, char sex, int age, int num) { 7 super(name, sex, age);//调用Person父类的构造方法 8 this.num = num; 9 } 10 // 11 public void study(){ 12 System.out.println(num+"号学生"+this.getName()+"正在学习..."); 13 super.introduce(); 14 } 15 // 16 public void introduce(){ 17 System.out.println("学号:" + num); 18 super.introduce();//调用Person父类的introduce方法 19 } 20 //get和set方法 21 public int getNum() { 22 return num; 23 } 24 25 public void setNum(int num) { 26 this.num = num; 27 } 28 }
Teacher:
1 public class Teacher extends Person{ 2 // 3 private String lesson; 4 5 //构造方法(继承了Person所以也有name,sex,age属性) 6 public Teacher(String name, char sex, int age, String lesson) { 7 super(name, sex, age);//调用Person父类的构造方法 8 this.lesson = lesson; 9 } 10 //方法 11 public void teach(){ 12 System.out.println(this.getName() + "老师正在讲" + this.lesson); 13 } 14 // 15 @Override 16 public void introduce(){ 17 super.introduce(); 18 System.out.println("讲" + lesson + "课程"); 19 } 20 //get和set方法 21 public String getLesson() { 22 return lesson; 23 } 24 25 public void setLesson(String lesson) { 26 this.lesson = lesson; 27 } 28 }
Test:
1 public class Test { 2 public static void main(String args[]){ 3 Student s1 = new Student("小米",'男',20,101); 4 s1.introduce(); 5 s1.study(); 6 } 7 }
结果为:
1 public class Test { 2 public static void main(String args[]){ 3 Student s2=new Student("小麦",'男',22,102); 4 s2.introduce(); 5 } 6 }
结果为:
1 public class Test { 2 public static void main(String args[]){ 3 Teacher t1=new Teacher("黎明",'男',40,"音乐"); 4 t1.introduce(); 5 t1.teach(); 6 } 7 }
结果为:
四、多态
具有表现多种形态的能力
同样的一条语句,多次执行,结果可能不同
1.引用类型之间的转换
自动转换:子类 => 父类
又称为类型的自动提升,向上转型,上溯转型
如果子类重写了父类的方法,调用该方法时,看实际类型(new后面的类型)
注意:用父类的引用去调用父类中的方法,子类特有的方法无法调用
强制转换
子转父后,可以强制转换回子类对象
类型自动提升后,可以强制转换回原类型或原类型的父类型
2.多态的实现方式
1)方法重载:静态多态,编译时多态,在程序编译期间,根据参数列表去匹配
2)方法重写:动态多态,运行时多态,在程序运行期间,根据对象的实际类型去选择执行哪个类中的方法
一般的多态都指方法重写所实现的多态,实现步骤:
- 要有继承关系和实现接口
- 要有方法重写
- 要有父类或接口引用去调用重写的方法(要有类型的自动提升)
实例一:
编码实现动物世界的继承关系:
动物(Animal)具有行为:吃(eat)、睡觉(sleep)
动物包括:兔子(Rabbit),老虎(Tiger)
这些动物吃的行为各不相同(兔子吃草,老虎吃肉);但睡觉的行为是一致的。
通过继承实现以上需求,并编写测试类AnimalTest进行测试。
Animal:
1 public class Animal { 2 //屬性 3 private String type; 4 private String name; 5 //构造方法 6 public Animal(String type, String name) { 7 this.type = type; 8 this.name = name; 9 } 10 //方法 11 public void eat(){ 12 System.out.println("动物需要吃东西维持生命"); 13 } 14 public void sleep(){ 15 System.out.println(type + name + "正在睡觉..."); 16 } 17 //get和set方法 18 public String getType() { 19 return type; 20 } 21 22 public void setType(String type) { 23 this.type = type; 24 } 25 26 public String getName() { 27 return name; 28 } 29 30 public void setName(String name) { 31 this.name = name; 32 } 33 }
Rabbit:
1 public class Rabbit extends Animal{ 2 //构造方法 3 public Rabbit(String name){ 4 super("兔子",name); 5 } 6 @Override 7 public void eat(){ 8 //super.eat(); 9 System.out.println(this.getType()+this.getName()+"正在吃萝卜...."); 10 } 11 public void jump(){ 12 System.out.println("兔子会跳"); 13 } 14 }
Tiger:
1 public class Tiger extends Animal{ 2 //构造方法 3 public Tiger(String name){ 4 super("老虎",name); 5 } 6 //方法(吃) 7 public void eat(){ 8 System.out.println(this.getType()+this.getName()+"正在吃兔子...."); 9 } 10 }
Person:
1 public class Person { 2 public void feed(Animal an){ 3 System.out.println("饲养员正在给" + an.getType() + an.getName() + "喂食"); 4 } 5 }
测试类Test1:
1 public class Test1 { 2 public static void main(String[] args) { 3 Tiger t1 = new Tiger("小黄"); 4 t1.sleep(); 5 t1.eat(); 6 } 7 }
结果:
1 public class Test1 { 2 public static void main(String[] args) { 3 Rabbit r1=new Rabbit("小白"); 4 r1.sleep(); 5 r1.eat(); 6 r1.jump(); 7 } 8 }
结果:
1 public class Test1 { 2 public static void main(String[] args) { 3 Tiger t1 = new Tiger("小黄"); 4 Animal an; 5 an=t1; 6 an.sleep(); 7 an.eat(); 8 } 9 }
结果:
1 public class Test1 { 2 public static void main(String[] args) { 3 Animal an=new Tiger("大黄"); 4 an.sleep(); 5 an.eat(); 6 7 } 8 }
结果:
1 public class Test1 { 2 public static void main(String[] args) { 3 Rabbit r1=new Rabbit("小白"); 4 5 Animal an=new Tiger("大黄"); 6 7 Tiger t2=(Tiger)an; 8 t2.eat(); 9 10 an=r1; 11 an.sleep(); 12 an.eat(); 13 14 Rabbit r2=(Rabbit) an; 15 r2.jump(); 16 } 17 }
结果:
创建一个Animal将其强制转换为Tiger则会报错类转换异常:
1 public class Test1 { 2 public static void main(String[] args) { 3 4 Animal an2=new Animal("动物","aa"); 5 6 Tiger t3=(Tiger) an2; 7 t3.eat(); 8 } 9 }
结果:
下面实现了多态:
1 public class Test1 { 2 public static void main(String[] args) { 3 Rabbit r1=new Rabbit("小白"); 4 5 Animal an=new Tiger("大黄"); 6 an.sleep(); 7 an.eat(); 8 9 an=r1; 10 an.sleep(); 11 an.eat(); 12 } 13 }
结果:
同时调用了sleep方法和eat方法,但是结果不同。
在创建一个测试类Test2:
1 public class Test2 { 2 public static void main(String[] args) { 3 Tiger t1=new Tiger("小黄"); 4 Tiger t2=new Tiger("小虎"); 5 Rabbit r1=new Rabbit("小白"); 6 Rabbit r2=new Rabbit("小灰"); 7 8 Person p=new Person(); 9 10 p.feed(t1); 11 p.feed(t2); 12 13 p.feed(r1); 14 p.feed(r2); 15 } 16 }
结果为:(调用了Person类的feed方法)
实例二:
对老师进行评估,评估方法(Leader):对老师(自我介绍[introduce]、讲课[teach])进行评估。体育老师(PTeacher)和音乐老师(MTeacher)继承Teacher
Teacher:
1 public class Teacher { 2 //属性 3 private String name; 4 private String lesson; 5 //构造方法 6 public Teacher(String name, String lesson) { 7 this.name = name; 8 this.lesson = lesson; 9 } 10 //方法 11 public void introduce(){ 12 System.out.println(lesson + "老师叫" + name); 13 } 14 public void teach(){ 15 System.out.println("讲解主要内容。。"); 16 System.out.println("布置作业"); 17 } 18 //get和set方法 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public String getLesson() { 28 return lesson; 29 } 30 31 public void setLesson(String lesson) { 32 this.lesson = lesson; 33 } 34 }
PTeacher:
1 public class PTeacher extends Teacher { 2 public PTeacher(String name){ 3 super(name,"体育"); 4 } 5 //方法重写 6 @Override 7 public void teach() { 8 System.out.println("先做热身运动。。"); 9 super.teach(); 10 } 11 }
MTeacher:
1 public class MTeacher extends Teacher { 2 public MTeacher(String name){ 3 super(name,"音乐"); 4 } 5 //方法重写 6 @Override 7 public void teach() { 8 System.out.println("先练发声..."); 9 super.teach(); 10 } 11 }
Leader:
1 public class Leader { 2 //评估方法:对老师(自我介绍、讲课)进行评估 3 public void judge(Teacher t){ 4 System.out.println("对"+t.getLesson()+"老师"+t.getName()+"进行评估:"); 5 t.teach(); 6 } 7 }
编写测试类Test:
1 public class Test { 2 public static void main(String args[]){ 3 PTeacher pt = new PTeacher("姚明"); 4 pt.introduce(); 5 pt.teach(); 6 } 7 }
结果:
1 public class Test { 2 public static void main(String args[]){ 3 MTeacher mt=new MTeacher("黎明"); 4 mt.introduce(); 5 mt.teach(); 6 } 7 }
结果:
1 public class Test { 2 public static void main(String args[]){ 3 PTeacher pt = new PTeacher("姚明"); 4 5 MTeacher mt=new MTeacher("黎明"); 6 7 Leader ld=new Leader(); 8 ld.judge(pt); 9 ld.judge(mt); 10 } 11 }
结果: