1.面向对象(重重重重重重重点)
1.1 什么面向对象(OOP,Object-Oriented Programming)
面向过程:凡事亲力亲为(所有的想要的东西,都需要自己一步一步去完成) 你是一个实现者
面向对象:找一个拥有此功能的人或者物件,帮助我们实现想要的功能或者东西 你是一个调用者
举例说明:面向对象和面向过程的区别
人的懒惰促进社会进步
面向过程: 人饿了 要吃饭 由此得出需求:吃饭
买菜 — 生火 — 择菜 – 洗洗 – 切菜 --炒菜 – 煮饭 – 吃
面向对象: 饿了 – 找饿了么 – 选外卖 – 坐家里面等
不再关注具体的实现过程,只关注最后的实现结果
请举例说明什么是面向对象思想:(以现场作为你的例子的源发地
2.2为什么说java是一种面向对象语言(能理解就理解,实在理解不了就先记着)
是因为java给我们封装了很多的功能jar包,这些jar包或者类库里面有各种各样帮我们实现我们想要的功能的类
比如: String Math Random Scanner
2.3面向对象的三大特征
封装,继承,多态
2.4类和对象
由需求引出类和对象
需求:存储全班所有同学的个人信息(姓名,性别,年龄,成绩) 由此引出类
类:一种数据类型(引用数据类型) 类是对现实生活中一类具有共同特征的事物的抽象 (抽象的)
案例:写一个学生类
造一辆汽车(宝马x21),首先确定车辆每个部位都需要什么东西,通过建模,通过画图工具
会先去造一张图纸,这张图纸画了你的车的各个部位(轮胎,车身长度,高度,内饰,大灯)(车的具体的属性)
这辆车会跑,会放歌,会自动驾驶,会自动泊车(车的功能或者叫做车都能做什么)
造汽车:
顶配 高配 中配 标配 低配 红色 绿色 白色 黑色 银色 灰色 实际存在的物件(实例又被称之为对象)
人:
人有姓名 性别 身高 年龄 帅不帅 身材好不好 人会跑 跳 吃 喝 睡觉
对象:是类的具体实例,一个类可以创建无数个对象(具体存在的)
举例子:汽车制造
案例:创建一个学生对象
对象的格式:
类名 对象名 = new 类名();
修饰符:
* public 公开的 在哪儿都能调用
- protected 受保护的 子类可以调用
- 默认的 同一个包下 可以调用 跨包就不行了
- private 私有的 只能本类内调用
2.5 六大组件介绍
成员变量: 定义在类中方法外的变量称之为成员变量
成员方法: 类中的方法就叫做成员方法
静态变量: 用static修饰的变量
静态方法: 用static修饰的方法就叫做静态方法
局部变量: 定义在方法中的变量被称之为局部变量 方法声明上的
构造方法: 用于创建对象使用的就叫做构造方法,
修饰符 类名(){
}
2.6面向对象的内存分析
栈:局部变量和方法的执行,没有初始化值
堆:new出来的东西 有初始化值
方法区:
class区:字节码文件
static区:static修饰的东西
2.7 局部变量和成员变量的区别
静态变量:可以被所以的对象共享
成员变量:定义与类中方法外,随着对象的创建而创建,随着对象的消失而消失,存储于堆内存,有默认值
局部变量:定义在方法内,随着方法的消失而消失,存储于栈内存,必须赋值才能被调用
2.8封装
1.成员变量私有化
什么是封装:成员变量私有化
为什么要用它:保证类的完整性,不允许别人随意修改类中属性或者代码
为了代码的安全性考虑
权限修饰符: private protected 默认的 private
2.private修饰的变量和方法不能被外界访问,只能被本类调用
那么针对这种情况,我们可以提供一套方法,这套方法就是给变量
进行赋值和取值操作的
3.this关键字的使用
4.案例封装一个员工对象
5.案例面向对象求长方形周长和面积
2.9构造方法
1.构造方法的格式:
修饰符 类名(){
方法体
}
2.构造方法的注意事项:
1.构造方法没有返回值,连void都没有
2.方法名和类名相同
3.构造方法可以被重载
3.构造方法什么时候被调用
使用new关键字的时候被调用
如果我们类里面没有写构造方法,那么系统会给我们默认创建一个无参的构造方法
如果我们写了,那么系统就不会给我们提供
4.如果构造方法被私有化了会出现什么情况
形参与实参
形参和实参在传递的时候 需要注意的事项
如果是引用类型 那么形参的改变会影响实参
如果是基本类型 那么形参的改变不会影响实参
多态
三个前提:
有继承关系
父类的引用指向子类的对象
方法的重写
四种调用
同名的成员变量: 父类的
同名的静态方法: 父类的
同名的成员方法: 子类的
同名的静态变量: 父类的
无法调用子类中独有的属性和方法
父类中独有: 父类的
二种转型
向上转型: Person p = new Teacher();
向下转型 Teacher t = (Teacher)p;
class Animal {
int num = 10;
static int age = 20;
public void eat() {
System.out.println("动物吃饭");
}
public static void sleep() {
System.out.println("动物在睡觉");
}
public void run(){
System.out.println("动物在奔跑");
}
}
class Cat extends Animal {
int num = 80;
static int age = 90;
String name = "tomCat";
public void eat() {
System.out.println("猫吃饭");
}
public static void sleep() {
System.out.println("猫在睡觉");
}
public void catchMouse() {
System.out.println("猫在抓老鼠");
}
}
class Test {
public static void main(String[] args) {
Animal am = new Cat();//向上转型
am.eat();//猫吃饭
am.sleep();//动物在睡觉
am.run();//动物在奔跑
System.out.println(am.num);//10
System.out.println(am.age);//20
am.catchMouse();//报错,无法调用子类独有
System.out.println(am.name);//报错,无法调用子类独有
Cat ct = (Cat)am;//向下转型
ct.sleep();//猫在睡觉
ct.run();//动物在奔跑
}
}
抽象类
用abstract 修饰的类:
抽象方法格式:
abstract 修饰符 返回值类型 方法名(参数列表);
抽象类的定义格式:
abstract class 类名{}
注意事项:
1. 抽象类中可以没有抽象方法,有抽向方法的类一定是抽象类
2. 抽象类不能创建对象,需要使用子类向上转型
3. 抽象的子类要么实现抽象类中所有的抽象方法,要么自己是一个抽象类
4. 抽象类有构造方法,但是不能创建对象,那么他的构造是用于给子类对象初始化的
5. abstract 不能和final共存
练习1:
创建一个抽象类,定义两个抽象方法
定义一个子类,继承抽象类,实现这两个抽象方法
使用抽象类的多态,调用这两个方法
/**
* 创建一个抽象类,定义两个抽象方法
定义一个子类,继承抽象类,实现这两个抽象方法
使用抽象类的多态,调用这两个方法
*
*/
public class AbstractTest {
public static void main(String[] args) {
A a = new B();//抽象类的多态
a.a();
a.b();
}
}
abstract class A{
public abstract void a();
abstract public void b();
}
class B extends A{
@Override
public void a() {
System.out.println("A");
}
@Override
public void b() {
System.out.println("b");
}
}
练习2:
定义一个抽象类形状,包含两个方法,求周长和面积
定义一个类长方形,实现抽象类中的方法
定义一个类圆,实现抽象类中的方法
在测试类中测试
/**
* 定义一个抽象类形状(Shape),包含两个方法,求周长和面积(抽象方法)
定义一个类长方形,实现抽象类中的方法 (长,宽) (构造方法)
定义一个类圆,实现抽象类中的方法 (半径) (构造方法)
在测试类中测试
创建一个长方形和圆,分别求周长和面积
创建一个方法,既可以求圆的周长面积,也可以求长方形的周长和面积
*/
public class AbstractTest2 {
public static void main(String[] args) {
Shape r = new Rect(20,10);
/*System.out.println(r.getPrimeter());
System.out.println(r.getArea());*/
Shape c = new Circle(4);
/*System.out.println(c.getPrimeter());
System.out.println(c.getArea());*/
print(r);
print(c);
}
public static void print(Shape s) {
System.out.println("周长为:" + s.getPrimeter());
System.out.println("面积为: "+ s.getArea());
}
}
abstract class Shape{
abstract public double getPrimeter();
abstract public double getArea();
}
class Rect extends Shape{
double length;
double width;
public Rect() {}
public Rect(double length,double width) {
this.length = length;
this.width = width;
}
public double getPrimeter() {
return 2*(length+width);
}
public double getArea() {
return length*width;
}
}
class Circle extends Shape{
public static final double PI = 3.14;
double r;
public Circle() {}
public Circle(double r) {
this.r = r;
}
public double getPrimeter() {
return 2*PI*r;
}
public double getArea() {
return PI*r*r;
}
}
继承关系和组合关系:
案例: 定义一个Person类,里面包含,姓名,年龄,性别和手机(品牌,型号,价格,颜色):
创建一个对象: 张三,18,男,手机(华为,p20,1888,“黑色”)
/**
* 组合关系
* 案例: 定义一个Person类,里面包含,姓名,年龄,性别和手机(品牌,型号,价格,颜色):
创建一个对象: 张三,18,男,手机(华为,p20,1888,"黑色")
*/
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.setName("张三");
p.setAge(18);
p.setGender('男');
Mobile m = new Mobile();
m.setBrand("华为");
m.setType("p20");
m.setColor("黑色");
m.setPrice(1888);
p.setMobile(m);
p.show();
Person p2 = new Person("李四",29,'女',new Mobile("小米","note8","白色",1000));
p2.show();
}
}
/**
* 继承: is a Teacher is a Person
* 组合: has a Person has a Mobile
* 聚合: has a
* Person 和 Mobile 关系就叫做组合关系
*/
class Person{
private String name;
private int age;
private char gender;
private Mobile mobile;//组合
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public Mobile getMobile() {
return mobile;
}
public void setMobile(Mobile mobile) {
this.mobile = mobile;
}
public Person() {
super();
}
public Person(String name, int age, char gender, Mobile mobile) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.mobile = mobile;
}
public void show() {
System.out.println("姓名:"+name+",年龄:"+age+",性别:"+gender+",品牌:"+mobile.getBrand()+",型号"+mobile.getType()+",颜色:"+mobile.getColor()+",价格:"+mobile.getPrice());
}
}
class Mobile{
private String brand;
private String type;
private String color;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Mobile() {
super();
}
public Mobile(String brand, String type, String color, double price) {
super();
this.brand = brand;
this.type = type;
this.color = color;
this.price = price;
}
}
练习3:
1)定义一个抽象类Animal,其中包括属性name,相关构造方法,抽象方法enjoy()表示动物高兴时动作。
2)定义Cat类继承于Animal类,其中包括属性eyesColor,相关构造方法,同时具体化父类中的抽象方法。
3)定义Dog类继承于Animal类,其中包括属性furColor,相关构造方法,同时具体化父类中的抽象方法。
4)定义Lady类,其中包括属性name,以及Animal 类型的属性pet表示女士所养的宠物,定义构造方法,生成女士对象时初始化姓名和她所养的宠物。
定义一个方法:myPetEnjoy表示此女士的宠物在高兴时的动作。提示:对于此类的定义中需要使用到多态性。
5)定义测试类。
public class AbstractTest3 {
public static void main(String[] args) {
Lady l1 = new Lady("张女士",new Cat("小花","红色"));
l1.myPetEnjoy();
Lady l2 = new Lady("王女士",new Dog("小白","绿色"));
l2.myPetEnjoy();
}
}
abstract class Animal{
String name;
public Animal() {
}
public Animal(String name) {
this.name = name;
}
abstract public void enjoy();
}
class Cat extends Animal{
String eyesColor;
public Cat() {}
public Cat(String name,String eyesColor) {
//this.name = name;
super(name);
this.eyesColor = eyesColor;
}
@Override
public void enjoy() {
System.out.println("喵~我的名字叫"+name+",我的眼睛是"+eyesColor+",我很高兴");
}
}
class Dog extends Animal{
String furColor;
public Dog() {}
public Dog(String name,String furColor) {
this.name = name;
this.furColor = furColor;
}
@Override
public void enjoy() {
System.out.println("汪~,我的名字是:"+name+",我的皮毛是"+furColor+",我很高兴");
}
}
class Lady {
String name;
Animal pet;
public Lady() {}
public Lady(String name,Animal pet) {
this.name = name;
this.pet = pet;
}
public void myPetEnjoy() {
pet.enjoy();
System.out.println("我叫"+ name+",我的宠物很高兴,我也很高兴");
}
}
接口
定义格式:
interface 接口名{}
注意事项:
1. 接口中只能定义常量,默认public static final修饰
2. 接口中只能定义抽象方法(1.8之前) 默认是public abstract 修饰
3. 接口不能创建对象,使用子类向上转型
4. 接口的子类: 实现了接口的类 class 子类名 implements 接口1,接口2{}
5. 接口的子类要么实现接口中所有的抽象方法要么自己是一个抽象类
6. 一个类可以实现多个接口,并且可以在继承类的同时实现多个接口
7. 接口中没有构造方法
8. jdk8之后接口中可以定义已经实现的方法,但是必须使用static/default 修饰
9. 接口不能实现接口,只能继承接口,并且可以多继承
class 子类名 implements 接口1,接口2{}
练习1:
定义一个接口,定义两个抽象方法,写一个类实现该接口,并实现里面的方法,使用接口多态创建对象,并调用方法
/**
* 1. 定义一个接口InterA, 里面包含一个抽象方法,一个常量值a=100
* 2. 定义一个接口,InterB,继承接口InterA, 在写一个抽象方法
* 3. 定义个类Test,
* 4. 定义一个类Demo 继承Test 并 实现 InterB,实现里面所有的抽象方法
* 5. 在测试类中,创建InterB 类型的变量,调用里面的方法
*/
public class InterfaceTest {
public static void main(String[] args) {
InterB b = new Demo();// 接口的多态
b.test();
b.test2();
}
}
interface InterA{
void test();
int a = 100;
}
interface InterB extends InterA{
public void test2();
}
class Test{
}
class Demo extends Test implements InterB{
@Override
public void test() {
System.out.println("test");
}
@Override
public void test2() {
System.out.println("test2");
}
}
练习2:
编写一个抽象类Animal,抽象类中包括属性:name(String类型),抽象方法:speak()。
编写一个宠物接口pet,接口中包括方法:eat()。
再编写一个类cat,实现该接口和抽象类中的所有方法。
speat(): “miao, my name is xxx”
eat(): “I want to eat some fish”
在main中进行测试,输出:
给猫赋值一个名字,调用speak,eat 方法
public class InterfaceTest2 {
public static void main(String[] args) {
Pet p = new Cat();
p.eat();
//p.speak();//speak 并不存在与Pet接口中,所有他是子类中独有的方法,在多态的时候,调不了
Animal a = new Cat("小花");
a.speak();
//a.eat();//不能调子中独有的
}
}
//the type animal is already defined: 代表本包中已经有该名字的类: 换一个名: 建一个包
abstract class Animal{
String name;
abstract public void speak();
}
interface Pet{
void eat();
}
class Cat extends Animal implements Pet{
public Cat() {}
public Cat(String name) {
this.name = name;
}
@Override
public void eat() {
System.out.println("I want to eat some fish");
}
@Override
public void speak() {
System.out.println("miao, my name is "+name);
}
}
练习3:
按如下要求编写Java程序:
(1)编写接口InterfaceA,接口中含有方法void printCapitalLetter()。
(2)编写接口InterfaceB,接口中含有方法void printLowercaseLetter()。
(3)编写非抽象类Print,该类实现了接口InterfaceA和InterfaceB。要求printCapitalLetter()方法实现输出大写英文字母表的功能,printLowercaseLetter()方法实现输出小写英文字母表的功能。
(4)再写一个主类Test,在main方法中创建Print的对象并赋值给InterfaceA的变量a,由变量a调用printCapitalLetter方法,然后再创建Print的对象并将该对象赋值给InterfaceB的变量b,由变量b调用printLowercaseLetter方法
public class InterfaceTest3 {
public static void main(String[] args) {
InterfaceA a = new Print();
a.printCapitalLetter();
//a.printLowercaseLetter();// 子类中独有
InterfaceB b = new Print();
b.printLowercaseLetter();
}
}
interface InterfaceA{
void printCapitalLetter();
}
interface InterfaceB{
void printLowercaseLetter();
}
class Print implements InterfaceA ,InterfaceB{
@Override
public void printLowercaseLetter() {
for(char i='a';i<='z';i++) {
System.out.println(i);
}
}
@Override
public void printCapitalLetter() {
for(char i='A';i<='Z';i++) {
System.out.println(i);
}
}
}
抽象类和接口的区别:
1.一个类最多只能继承一个抽象类,但是可以实现多个接口
2.抽象类中既可以定义变量也可以定义常量,接口中只能定义常量
3.抽象类中既可以定义抽象方法,也可以定义非抽象方法,接口中能定义抽象方法(jdk8之前)
4.接口中没有构造方法,抽象类中有构造方法
5.接口只能继承接口不能实现接口,并且可以多继承