一、封装
封装:对象代表什么,就封装对应的数据,并提供数据相应的行为
1.访问权限
访问权限 本类 本包的类 子类 非子类的外包类 public 是 是 是 是 protected 是 是 是 否 default(默认空白) 是 是 否 否 private 是 否 否 否 1、public: 所修饰的类、变量、方法,在内外包均具有访问权限;
2、protected: 这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,但只对同包的类是可访问的,对外包的非子类是不可以访问;
3、包访问权限(default): 只对同包的类具有访问的权限,外包的所有类都不能访问;
4、private: 私有的权限,只对本类的方法可以使用;注意: 要区分开 protected 权限、包访问权限,正确使用它们;
- 当某个成员能被所有的子类继承,但不能被外包的非子类访问,就是用protected;
- 当某个成员的访问权限只对同包的类开放,包括不能让外包的类继承这个成员,就用包访问权限;
使用访问权限控制的原因:
1)使用户不要碰触那些他们不该碰触的部分;
2)类库设计者可以更改类的内部工作的方式,而不会担心这样会对用户产生重大影响;
2.static静态关键字
static关键字,能够让变量被固定在一个值,在下次赋值之前都保持这个值
适用范围:可以修饰成员变量,也可以修饰成员方法
使用方法:最好是用类名调用,不要用对象名调用,因为所有对象共享这个静态变量(静态优先于对象在类里存在)使用场景:关键看能否共享
A. 学生类
一个学生集合,这些学生都是一个班的,有同样一个老师,在第一次输入老师姓名之后就不需要再次输入了,这时候用static
public class Student {
//姓名、年龄、性别
//新增:老师的姓名
private String name;
private int age;
private String sex;
private static String teacher;//定义静态成员变量老师的姓名
public Student() {
}
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//行为:学习
public void Study()
{
System.out.println(this.name+"正在学习");
}
public String getTeacher(){
return teacher;
}
public static void setTeacher(String teacher){
Student.teacher =teacher;
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void Show() {
System.out.println(name+","+age+","+sex+","+teacher);
}
}
B.主函数
调用学生类里的老师姓名时,直接使用“类名.成员变量”的形式
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
Student stu=new Student();
System.out.println("请输入学生姓名");
stu.setName(in.next());
System.out.println("请输入学生年龄");
stu.setAge(in.nextInt());
System.out.println("请输入学生性别");
stu.setSex(in.next());
System.out.println("请输入学生老师的姓名");
Student.setTeacher(in.next());
stu.Study();//学生1学习
stu.Show();
Student stu1=new Student();
System.out.println("请输入学生姓名");
stu1.setName(in.next());
System.out.println("请输入学生年龄");
stu1.setAge(in.nextInt());
System.out.println("请输入学生性别");
stu1.Study();//学生2学习
stu1.Show();
stu.Show();
}
}
3.工具类
javabean类:用来描述一类事物的类
测试类:用来检查其他类是否书写正确,main方法的类
工具类:不是用来描述一类事物的,而是帮我们做一些事情的类工具类:
1.(private)构造方法要私有*因为创建工具类的对象没有任何意义
(系统默认空参构造)
2.成员方法要静态
A.学生类的工具类(获取学生集合中学生的最大年龄)
学生类就是static里的学生类
import java.util.*;
public class StudentUtil {
private StudentUtil(){//构造方法私有化
}
//学生类的工具类
public static int GetAgeMax(ArrayList<Student> list)
{
int max=list.get(0).getAge();
for (int i = 1; i < list.size(); i++) {
int num=list.get(i).getAge();
if(max<num)
max=num;
}
return max;
}
}
主函数
import java.util.*;
public class TestDemo1
{
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
ArrayList<Student> list=new ArrayList<>();
Student stu1=new Student("张三",21,"男");
Student stu2=new Student("三",22,"男");
Student stu3=new Student("张",23,"男");
list.add(stu1);
list.add(stu2);
list.add(stu3);
int maxage=StudentUtil.GetAgeMax(list);
System.out.println(maxage);
}
}
B.数组工具类(输出一维int数组,获取一维double数组的平均值)
public class ArrayUtil {
private ArrayUtil(){//构造方法私有化
}
public static String printArr(int[] arr){
//只考虑整数一维数组,其它可以重写方法
String a="[";
for (int i = 0; i < arr.length-1; i++) {
a+=arr[i]+",";
}
return a+arr[arr.length-1]+"]";
}
public static double getAverage(double[] arr)
{//返回平均值
double average=0;
for (int i = 0; i < arr.length; i++) {
average+=arr[i];
}
average/=arr.length;
return average;
}
}
主函数
import java.util.*;
public class TestDemo {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
double[] test1={1.1,2.2,3.3,4.4};
int[] test2={1,2,3,4,5};
System.out.println(ArrayUtil.getAverage(test1));
System.out.println(ArrayUtil.printArr(test2));
}
}
二、继承
1.概念
封装:对象代表什么,就封装对应的数据,并提供数据相应的行为
继承:为解决不同类存在的共性问题,产生了父类和子类的概念,少写重复的代码
1.类和类之间存在相同的内容
2.子类是父类的一种,子类属于父类
子类 extends 父类
1.单继承规则
Java只支持单继承,不支持多继承,但支持多层继承
1.一个子类只能有一个父类
2.子类继承父类,父类继承父类的父类(直接父类),子类也可以使用父类的父类的方法(间接父类 )
2.不可被继承的内容
1.构造方法不可被继承
2.成员变量可以被继承,私有度一样被继承
3.私有的成员方法不可以被继承
3.this super
this直接引用当前类的内容(this不可以在静态方法中使用)
super直接继承引用父类的内容
4.就近原则
方法调用和成员调用都满足就近原则
5.重写@Override
方法重写:当父类中方法不能满足子类现在的需求时
@Override (重写注解:写给虚拟机看的)
1.static、私有方法不能用重写
2.重写方法的名称、形参列表必须与父类中一致
3.只有被添加到虚方法表中的方法才能重写
4.子类访问权限必须大于等于父类
5.子类返回值类型必须小于等于父类
2. 宠物类
属性:名字
行为:吃饭,喝水
public class Pets {
//宠物类
private String name;
public Pets(String name)
{
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void Eat(){
System.out.println(this.getName()+"吃饭");
}
public void Drink(){
System.out.println(this.getName()+"喝水");
}
}
1.猫类
行为(除宠物共有行为以外):抓老鼠
public class Cat extends Pets{
//猫类是宠物类的子类
public Cat(String name) {
super(name);//继承父类的构造对象
}
public void CatchMouse(){
System.out.println(this.getName()+"抓老鼠");
}
}
a.布偶猫
行为(重写):抓不到老鼠
public class Ragdoll extends Cat{
//布偶猫类是猫的子类
public Ragdoll(String name)
{
super(name);
}
@Override
public void CatchMouse()
{
System.out.println("抓不到");
}
}
b.中华田园猫
public class ChineseCat extends Cat{
//中国田园猫是猫类的子类
public ChineseCat(String name)
{
super(name);
}
}
2.狗类
行为(除宠物共有行为以外):看家、拆家、蹭一蹭(撒娇)
public class Dog extends Pets{
//狗类是宠物类的子类
public Dog(String name) {
super(name);
}
public void Security(){
System.out.println(this.getName()+"看家");
}
public void DesHouse(){
System.out.println(this.getName()+"拆家");
}
public void Rub(){
System.out.println(this.getName()+"蹭一蹭");
}
}
a.哈士奇
public class Husky extends Dog{
//哈士奇类是狗类的子类
public Husky(String name)
{
super(name);
}
}
b.泰迪
public class Taddy extends Dog{
//泰迪类是狗类的子类
public Taddy(String name)
{
super(name);
}
}
c.沙皮狗
行为(重写):吃饭(吃狗粮,也吃骨头)
public class Shappy extends Dog{
public Shappy(String name)
{
super(name);
}
@Override
public void Eat()
{
System.out.println(this.getName()+"吃狗粮,也吃骨头");
}
}
d.中华田园犬
行为(重写):吃饭(吃剩饭)
public class ChineseDog extends Dog{
public ChineseDog(String name)
{
super(name);
}
@Override
public void Eat()
{
System.out.println(this.getName()+"吃剩饭");
}
}
3.主函数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
//创建一个布偶猫对象
Ragdoll cat1=new Ragdoll("布偶猫");
//创建一个中国狸花猫对象
ChineseCat cat2=new ChineseCat("中国狸花猫");
//创建一个哈士奇对象
Husky dog1=new Husky("哈士奇");
//创建一个泰迪对象
Taddy dog2=new Taddy("泰迪");
//创建一个沙皮狗对象
Shappy dog3=new Shappy("沙皮狗");
cat1.CatchHouse();
cat2.CatchHouse();
dog1.Rub();
dog2.DesHouse();
dog3.Eat();
}
}
3. 饭店类
1.人员类
属性:工号、姓名、薪水
行为:工作、吃饭
public class Person {
private String id;//工号
private String name;//姓名
private int salary;//薪水
public Person() {
}
public Person(String id, String name, int salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
public void Do_work()
{//工作
}
public void Eat()
{//吃饭
System.out.println(this.getName()+"吃米饭");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
2.经理类
属性(除人员共有属性以外):管理奖金
行为(重写):工作(管理其他人)
public class Manager extends Person{
private int bonus;//管理奖金
public Manager(String id,String name,int salary,int bonus)
{
super(id, name, salary);
this.bonus=bonus;
}
@Override
public void Do_work()
{
System.out.println(this.getName()+"管理其他人");
}
}
3.厨师类
行为(重写):工作(炒菜)
public class Cooker extends Person{
public Cooker(String id,String name,int salary)
{
super(id, name, salary);
}
@Override
public void Do_work()
{
System.out.println(this.getName()+"炒菜");
}
}
4.主函数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
//定义一个经理对象
Manager p1=new Manager("1","张三",4000,2000);
//定义一个厨师对象
Cooker p2=new Cooker("2","李四",5000);
//调用经理工作、吃饭
p1.Do_work();
p1.Eat();
//调用厨师工作、吃饭
p2.Do_work();
p2.Eat();
}
}
三、多态
1.概念:
a.多态的优点和弊端
多态:同类型的对象,表现出的不同形态
优势:
1.多态形势下,右边对象可以实现解耦合,便于扩展和维护
业务逻辑发生改变时,后续代码无需修改
2.定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性和便利
弊端:
不能调用父类里没有的东西(解决方法:转换回子类)
b.多态的实现要求
应用场景:注册方法的形参(能接收所有可能注册的对象类型)
表现形式:父类类型 对象名称=子类对象
前提:
1.有继承关系
2.父类引用指向子类对象
3.有方法重写(至少有一个子类对象重写过此方法)
c.调用成员的特点
例:Animal a=new Dog();
调用成员的特点:
变量调用:编译看左边,运行也看左边
//编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功;如果没有,编译失败
//运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
理解:主要看成员对象的类型是父类还是子类方法调用:编译看左边,运行看右边
//编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法
//运行看右边:java运行代码的时候,实际上运行的是子类中的方法
d.类型强制转换和instanceof
变量名 instanceof 类名 (判断变量是否属于类)
强制类型转换
if(a instanceof Dog d)
d.lookHome
else if(a instanceof Cat c)
c.catchMouse
else
System.out.println("找不到这个类型");
2.注册逻辑中的多态
A.人员类
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void Show(Person p)
{
}
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;
}
}
B.学生类
class Student extends Person {
public Student(String name,int age)
{
super(name,age);
}
@Override
public void Show(Person p)
{
System.out.println(this.getName()+"同学举了个手");
}
}
C.管理员类
class Administer extends Person {
public Administer(String name,int age)
{
super(name,age);
}
@Override
public void Show(Person p)
{
System.out.println("管理员"+this.getName()+"来了个后空翻");
}
}
D.老师类
class Teacher extends Person{
public Teacher(String name,int age)
{
super(name,age);
}
@Override
public void Show(Person p)
{
System.out.println(this.getName()+"老师打了个哈欠");
}
}
E.主函数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
//定义老师对象
Teacher p1=new Teacher("张三",26);
//定义学生对象
Student p2=new Student("李四",21);
//定义管理员对象
Administer p3=new Administer("王五",50);
//p1.Register(p1);等价
Register(p1);
Register(p2);
Register(p3);
}
public static void Register(Person p)
{
p.Show(p);
}
}
3.抚养动物中的多态
A.动物类
class Animal {
private int age;
private String color;
public Animal(int age,String color)
{
this.age=age;
this.color=color;
}
public void Eat(String something)
{
System.out.println("吃"+something);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
B.狗类
class Dog extends Animal{
public Dog(int age,String color)
{
super(age,color);
}
@Override
public void Eat(String something)
{
System.out.println(this.getAge()+"岁的"+this.getColor()
+"颜色的狗,两只前腿死死地抱住"+something+"猛吃");
}
public void lookHome()
{
System.out.println("看家");
}
}
C.猫类
class Cat extends Animal{
public Cat(int age,String color)
{
super(age,color);
}
@Override
public void Eat(String something)
{
System.out.println(this.getAge()+"岁的"+this.getColor()
+"颜色的猫咪眯着眼睛侧着头吃"+something);
}
public void catchMouse(){
System.out.println("逮老鼠");
}
}
D.人员类
class Person{
private String name;
private int age;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
public void KeepPet(Animal animal,String something)
{
if(animal instanceof Dog)
System.out.println(this.age+"岁的"+this.name+"喂养了一只"+animal.getColor()
+"颜色的"+this.getAge()+"岁的狗");
else if(animal instanceof Cat)
System.out.println(this.age+"岁的"+this.name+"喂养了一只"+animal.getColor()
+"颜色的"+this.getAge()+"岁的猫");
animal.Eat(something);
}
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;
}
}
E.主函数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("请输入动物的年龄: 请输入动物的颜色");
Animal dog=new Dog(in.nextInt(),in.next());
System.out.println("请输入动物的年龄: 请输入动物的颜色");
Animal cat=new Cat(in.nextInt(),in.next());
System.out.println("请输入抚养人的姓名: 请输入抚养人的年龄");
Person p=new Person(in.next(),in.nextInt());
System.out.println("请输入动物吃的东西");
p.KeepPet(dog,in.next());
System.out.println("请输入动物吃的东西");
p.KeepPet(cat,in.next());
}
}