JAVA从入门到精通------基础篇------JAVA三大特性

1、封装

概念:尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限

当我们给属性赋值的时候,当不符合语法错误时,还要有实际意义,假如说定义年龄定义10000岁这显而是不现实的,那为了杜绝这种事的发生,我们应该进行判断

封装就是把属性进行私有了,通过get和set方法把属性进行有效的判断,这样在类的外部就只能通过set方法来赋值


封装的话,就只能用set来赋值才可以进行 过滤脏数据 如果用构造器赋值,哪怕是用set来进行封装的话也无法过滤脏数据

set方法 和 get方法

运用set方法在属性进行判定,在get方法进行输出

public class Demo4 {
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		
	
		if(age<100||age>0) {
			
			this.age = age;
		
		}else{
			
			this.age = 0;
	}
	
		
  }
}

外界访问不可直接访问属性,也就是说直接.属性,是不可以的,要.set 或者是 .get

当new这个类的时候如果类里有一个属性是用了其他类赋值那就得是.set().get() 

取值就是.get().get()

get和set方法是外界访问私有属性的唯一通道,方法内部可对数据进行检测和过滤

public class Person {
	private String name;
	private int age;
	
	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 class Student {
	private Person studentPerson;

	//只定义一个就可以,因为这只是一个中介,通过它这个地址去找到Person里边的地址,建立联系
	
	public Person getStudentPerson() {
		return studentPerson;
	}

	public void setStudentPerson(Person studentPerson) {
		this.studentPerson = studentPerson;
	}
	
	
}

定义一个就可以,因为这只是一个中介,通过它这个地址去找到Person里边的地址,建立联系

public class Demo {
	public static void main(String[] args) {
		Person p = new Person();
		p.setName("张三");
		p.setAge(20);
		
		Student stu = new Student();
		
		stu.setStudentPerson(p);
		stu.setStudentPerson(p);
		
		//首先要new对象,栈里的变量p进行接收,两者建立联系,然后把p传到里边这个新的栈里
		//就能找到堆里new的对象
		
		//如果我把stu.setStudentPerson(p)里的p变成new Person().setName
		//这样是不行的,因为这样虽然new出来了但是栈里没有,所以我们会报错,
		//这样的话堆里的地址固定不下来
		System.out.println(stu.getStudentPerson().getName());
		
		System.out.println(stu.getStudentPerson().getAge());
	}
}

        首先要new对象,栈里的变量p进行接收,两者建立联系,然后把p传到里边这个新的栈里
        就能找到堆里new的对象
        
        如果我把stu.setStudentPerson(p)里的p变成new Person().setName
        这样是不行的,因为这样虽然new出来了但是栈里没有,所以我们会报错,
        这样的话堆里的地址固定不下来 


2、继承

把一个笼统的有相同属性的类叫做父类

动物这个类就是狗的父类

public                                             同一项目下都可以访问

protected                                       同一包下,以及不同包的子类下

默认修饰符                                    同一包下

private                                           当前类下


1、语法

extends来继承父类

子类 extends 父类


2、应用

产生继承关系之后子类可以使用父类中的属性和方法,也可以定义子类独有的子类和方法

当调用父类时想调用子类就需要instanceof

 

 

如果父类属性不封装和继承   想不用.get  直接super +  那样的话父类必须得用static修饰

封装的话  get取     不封装的话  属性用static来修饰

方法的话    无static      子类调用父类的方法 需要使用super.方法名

                   static修饰  类名 . 方法名

继承的话,父类里有的属性就不需要在子类里边重新写了,直接super.来调用父类就可以了

new的时候直接.赋值就可以了 父类子类都可以 父类用super 子类用this

要是有构造器的话看下图


3、好处

即提高代码的复用性,又提高代码的可扩展性


4、调用方式

super调用父类

this调用子类,也可以说是当前正在写的类

子类构造器调用父类的构造器,首先保证super()里的形式父类要以构造器的形式
体现出来,其次就要保证父类构造器写的方法要this

有参构造器,,必须加this

在方法中,全局变量和局部变量名字相同时,this表示调用当前类的全局变量,如果是方法里的局部变量可以直接 + 

其实方法里要是全局变量和局部变量不重名,调用全局变量的也是this. 局部变量里的直接 + 就行


5、继承的特点

Java为单继承,一个类只能有一个直接父类,但可以多极继承,属性和方法诸暨叠加

构造器只创建本类的对象,不可继承


6、方法的重写与重载

重写(Override)

重写指的是,当父类提供的方法无法满足子类需求时,可在子类中定义和父类相同的方法进行重写

方法重写原则:

方法名称。参数列表,返回值类型必须与父类相同

访问修饰符可与父类相同或是比父类更宽泛

方法重写的执行

子类重写父类方法后,调用时优先执行子类重写后的方法

方法前名和父类都一样,但是访问修饰符不能比父类更严格

重载

指一个类中定义多个同名的方法,但是同名不同参


综合案例

员工管理系统

员工管理系统

首先定义 五个类
              员工类(父类)
              Employee      
        			    姓名 性别 地址 编号                      工作
              
              程序员类(继承员工类)
              programmer
        
              		    姓名 性别 地址 编号 bug数             编码工作
              
              
              项目经理类(继承员工类)
              
              ProjectManager      
              		    姓名 性别 地址 编号 项目数		  管理项目
              	
              菜单类(用来写功能)   
              Menue
             			查看所有员工   员工入职   员工信息维护   员工信息更改   删除员工
              	
              输出类用来输出
        			   	main方法
package com.project.javaempsys;

//父类
public class Employee {
	
	//定义无参构造器
	public Employee(){
		super();
	}
	
	//定义有参构造器
	public Employee(String name,char sex,String address,String id) {
		
		super();
		this.name = name;
		this.sex = sex;
		this.address = address;
		this.id = id;
		
	}
	
	
	//姓名
	private String name;
	
	//性别
	private char sex;
	
	//地址
	private String address;
	
	//编号
	private String id;
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public char getSex() {
		return sex;
	}
	
	public void setSex(char sex) {
		this.sex = sex;
	}
	
	public String getAddress() {
		return address;
	}
	
	public void setAddress(String address) {
		this.address = address;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	
	
	//写一个工作的方法
	public void work() {
		
		System.out.println("员工工作");
		
	}
	
}
package com.project.javaempsys;

public class Programmer extends Employee{
	
	public Programmer() {
		
		super();
		
	}
	
	public Programmer(String name,char sex,String address,String id,int bugNum) {
		
		//调用父类的构造器
		super(name,sex,address,id);
		//父类没有bugNum自己单独this
		this.bugNum = bugNum; 
		
	}
	
	//bug数量
	private int bugNum;

	public int getBugNum() {
		return bugNum;
	}

	public void setBugNum(int bugNum) {
		this.bugNum = bugNum;
	}

	//方法的重写
	@Override
	public void work() {
		
		System.out.println("我是程序员\t" + super.getName() + "\t我的性别是\t" + super.getSex() 
		                   +"\t我家住在\t" + super.getAddress() + "\t我的工作编号是\t" 
				           + super.getId() + "\t我的bug产生数量是\t" + this.bugNum);
		
	}
	
	
	
}
package com.project.javaempsys;

public class ProjectManager extends Employee{
	
	public ProjectManager() {
		
		super();
		
	}
	
	public ProjectManager(String name,char sex,String address,String id,int projectNum) {
		
		//调用父类方法的构造器
		super(name,sex,address,id);
		//父类没有projrctNum自己单独this
		this.projectNum = projectNum;
		
	}

	private int projectNum;

	public int getProjectNum() {
		return projectNum;
	}

	public void setProjectNum(int projectNum) {
		this.projectNum = projectNum;
	}
	
	//方法的重写
	@Override
	public void work() {
		
		System.out.println("我是项目经理\t" + super.getName() + "\t我的性别是\t" + super.getSex() 
		                   +"\t我家住在\t" + super.getAddress() + "\t我的工作编号是\t" 
				           + super.getId() + "\t我的bug产生数量是\t" + this.projectNum);
		
	}
}
package com.project.javaempsys;

import java.util.Scanner;

//菜单类,员工系统的操作
public class Menue {
	//声明一个数组存放员工
	//长度定义为公司员工总数量
	//放在方法外,定义为全局变量
	//不能放在方法内,那就是局部变量了
	Employee[] arry = new Employee[10];
	
	//调用Scanner流
	Scanner input = new Scanner(System.in);	
	
	//初始化员工1
	public void initEmp() {
	
	Programmer p1 = new Programmer("张青",'男',"北京市海淀区","H001",30);
	ProjectManager p2 = new ProjectManager("王爽",'女',"上海市黄浦区","G002",5);
	Programmer p3 = new Programmer("李涛",'男',"深圳市龙华区","H003",25);
	
	//将员工存入数组
	//无形中进行了向上类型转换,子类类型转换为父类类型
	//【说明】 父类类型的数组是可以存放子类对象的
	arry[0] = p1;
	arry[1] = p2;
	arry[2] = p3;
	
	}
	
	
	
	
	//写功能
	public void printMeneu() {
		
	
		//调用数组
		this.initEmp();

		System.out.println("*******************************");
		System.out.println("***********员工管理系统*********");
		System.out.println("*******************************");
		
		System.out.println("");
		System.out.println("");
		
		System.out.println("欢迎您使用本系统!");
		System.out.println("");
		
		char isContinue = 'y';
		
		do {
			
			System.out.println("1、查看所有员工");
			System.out.println("2、员工入职");
			System.out.println("3、员工信息更改");
			System.out.println("4、员工信息查询");
			System.out.println("5、删除员工");
			
			System.out.println("");
			
			System.out.println("请输入您的选项");
			
			System.out.println("");
			
			//写一个num值进行switch选择
			int num = input.nextInt();
			
			switch(num) {
				
				case 1:
					
					//查看所有员工   方法
					this.Show();
					break;
					
				case 2:
					this.addEmp();
					//员工入职   方法
					
					break;
					
				case 3:
					
					//员工信息更改   方法
					this.editEmp();
					break;
					
				case 4:
					
					//员工信息查询   方法
					this.selectEmp();
					break;
					
				case 5:	
					
					//删除员工   方法
					this.deleteEmp();
					break;
					
				default :
					System.out.println("暂未开放其他功能 请重新输入");
			}
			
			System.out.println("");
			System.out.println("请问是否继续其他操作");
			System.out.println("继续其他操作请输入 y ");
			System.out.println("退出请输入 n ");
			
			System.out.println("");
			isContinue = input.next().charAt(0);
			
		}while(isContinue == 'y');
		
		if(isContinue == 'n') {
			
			System.out.println("");
			System.out.println("感谢您使用本系统!");
			
		}
		
	}
	
	
	//查看所有员工方法
	//-------------------------------------------------------------------------------
	
    public void Show() {

    	System.out.println("员工姓名\t" + "\t员工性别\t"+"\t员工地址\t"+
    						"\t员工Id\t"+"\tbug数\\项目数\t");
    	//遍历员工数组 arry
    	for(int i=0;i<arry.length;i++) {
    		
    		//每个数组元素就是一个对象,就是一个new出的堆内存地址
            //因为数组的长度是10,所以如果直接循环调用的话,只有到2才被new,从3开始
    		//就为空了,空的话调用方法无法调用,会造成空指针异常
    		
    		//现在就要想办法阻止情况发生,当判断到空的时候就要停止输出
    		
    		if(arry[i] != null) {
    			System.out.print(arry[i].getName()+ "\t"+"\t"+arry[i].getSex()+"\t"
    		                      +"\t"+arry[i].getAddress()+"\t"+arry[i].getId()+"\t"
    		                      +"\t");
    			
    			//截至目前为止输出的是一直到地址,还有bug数和项目数
    			//想办法输出进行判断,是项目经理的输出项目经理,是程序员的输出程序员
    			
    			//可以判断每个对象的原始类型是什么,也就是子类是什么,然后因为目前是employee
    			//不是子类,父转子转不了可以进行强制转换  使用关键字instanceof
    			//instanceof 用于判断某个对象是否是指定的 类 类型,它返回的是一个boolean值
    			
    			//用法  :  对象  instanceof  指定的类类型
    			
    			//判断如果当前类型 的 原始类型 为Programmer的时候
    			if(arry[i] instanceof Programmer) {
    				//定义一个Programmer类型的变量p 将Employee类型的arry[i] 强制转换为 Programmer类型
    				Programmer p  = (Programmer)arry[i];
    				System.out.print("\t" + p.getBugNum()+"\t");
    			}
    			
    			//判断如果当前类型 的 原始类型 为ProjectManager的时候
    			if(arry[i] instanceof ProjectManager) {
    				
    				//定义一个ProjectManager类型的变量p
    				//强制将现在的父类Employee类型的arry[i]转换成原始类型ProjectManager类型
    				ProjectManager p =(ProjectManager)arry[i];
    				System.out.print("\t" + p.getProjectNum() + "\t");
    			}
    			
    			//换行
    			System.out.println("");
    			
    		}
    	}

    }
    
    //员工入职方法
    //-------------------------------------------------------------------------------
    
    //先写一个向数组中添加元素的方法   参数为Employee类型的emp
    //因为我们的数组本身就是一个Employee类型的
	public void addAry(Employee emp) {
	    //先定义一个boolean值为false
	    //用true和false来判断员工人数是否已满,
		//因为数组arry的长度我们就定义为10,所有不能超过10,要不然就加不进去,
	    //造成数组下角标越界
		boolean flag = false;
		//for循环从头开始找到为null的数组
		for(int i=0;i<arry.length;i++) {
			//当arry[i] 查询到是空的时候
			if(arry[i] == null) {
				//将flag变为true
				flag = true;
				//把参数emp传入进arry[i]中,进行赋值,到时候这个空的arry[i]就有元素了
				arry[i] = emp;
				//赋完值接没有必要接着循环了,直接break跳出
				break;
			}
		}
	    //如果遍历完仍是false则证明数组的每个索引用到了之后都不是null,也就是说公司人满了
		if(flag == false) {
			System.out.println("员工编制已满,不能办理入职");
			//如果遍历完之后,为true了则证明还有空的  值为null的  数组元素
		}else if(flag == true){
			System.out.println("成功办理入职");
		}
	}
    public void addEmp() {
    	
    	
    	System.out.println("请输入你入职的身份:   1、程序员       2、产品经理");
    	int num = input.nextInt();
    	System.out.println("请输入你的员工编号:");
    	String id = input.next();
    	System.out.println("请输入你的姓名:");
    	String name = input.next();
    	System.out.println("请输入你的性别:");
    	char sex = input.next().charAt(0);
    	System.out.println("请输入你的地址:");
    	String address = input.next();
    	
    	if(num == 1) {
    		System.out.println("请输入你预计的bug数");
    		int bugNum = input.nextInt();
    		//将bugNum传到后边
    		Programmer pg = new Programmer(name,sex,address,id,bugNum);
    		//因为定义了employee类型的emp参数
    		//数据类型自动转换,pg为programmer类型
    		//低转高  所以直接就能传入employee类型
    		this.addAry(pg);
    	}else if(num == 2) {
    		System.out.println("请输入你管理的项目数");
    		int projectNum = input.nextInt();
    		//将projectNum传入到后边
    		ProjectManager pj = new ProjectManager(name,sex,address,id,projectNum);
    		//因为定义了employee类型的emp参数
    		//数据类型自动转换,pg为programmer类型
    		//低转高  所以直接就能传入employee类型
    		this.addAry(pj);
    	}
    	
    }
    
    //员工信息更改 方法
    //-------------------------------------------------------------------------------
    
    public void editEmp() {
    	System.out.println("请输入你要修改的员工编号");
    	//因为id是String类型的
    	String id = input.next();
    	//遍历循环找到指定id的那个数组元素
    	for(int i=0;i<arry.length;i++) {
    		//需要用.equals来判断id和arry[i]通过get得到的id是否是一个
    		if(arry[i].getId().equals(id)) {
    			//询问是否要修改某个信息
    			System.out.println("是否要修改员工的名字?y/n");
    			//用Scanner流定义一个char类型来输入y还是n
    			char isName = input.next().charAt(0);
    			
    			if(isName == 'y') {
    				System.out.println("请输入要修改后的名字:");
    				String name = input.next();
    				arry[i].setName(name);
    			}
    			
    			System.out.println("是否要修改员工的性别?y/n");
    			char isSex = input.next().charAt(0);
    			if(isSex == 'y') {
    				System.out.println("请输入要修改之后的性别");
    				char sex = input.next().charAt(0);
    				arry[i].setSex(sex);
    			}
    			
    			System.out.println("是否要修改地址?y/n");
    			char isAddress = input.next().charAt(0);
    			if(isAddress == 'y') {
    				System.out.println("请输入修改之后的地址");
    				String Address = input.next();
    				arry[i].setAddress(Address);
    			}
    			
    			//判断arry[i]是不是Programmer
    			if(arry[i] instanceof Programmer) {
    				System.out.println("是否要修改bug数量?y/n");
        			char isBug = input.next().charAt(0);
        		    if(isBug == 'y') {
        		    	//强制转换
        		    	Programmer pg = (Programmer)arry[i];
        		        System.out.println("请输入修改后的bug数量:");
        		        int bugNum = input.nextInt();
        		        pg.setBugNum(bugNum);
        		    }
    			}
    			
    			//当instanceof 来判断是不是指定的原始类时  
    			//当判断进去之后就要用强制转换后的来调用原始类里边的方法
    			//因为本身是employee类型的,它是父类
    			//直接arry[i] . 的话 只能调用employee里的方法
    			if(arry[i] instanceof ProjectManager) {
    				System.out.println("是否要修改管理的项目数?y/n");
    				char isProNum = input.next().charAt(0);
    				if(isProNum == 'y') {
    					//强制转换
    					ProjectManager pm = (ProjectManager)arry[i];
    					System.out.println("请输入修改后的项目数量");
    					int proNum = input.nextInt();
    					pm.setProjectNum(proNum);
    				}
    			}
    			System.out.println("信息修改成功!");
    			//更新一遍信息
    			this.Show();
    			break;
    		}
    		
    	}
    }
    
    //员工信息查询方法
    //-------------------------------------------------------------------------------
    
    public void selectEmp() {
    	System.out.println("请输入你要查询的员工信息:");
    	String name = input.next();
    	//for循环遍历来找输入的名
    	for(Employee emp : arry) {
    		//限定范围 不是空数组,因为空数组里边没有值
    		if(emp != null) {
    			//因为是String类型的 所以用.equals()来判断
    			if(name.equals(emp.getName())) {
    				System.out.println("员工姓名\t" + "\t员工性别\t"+"\t员工地址\t"+
    						"\t员工Id\t"+"\tbug数\\项目数\t");
    				System.out.println(emp.getName() + "\t" + "\t" + emp.getSex()+ "\t" 
    			                       + emp.getAddress() + "\t" + "\t" + emp.getId() + "\t");
    				//判断每个类型的原始类型是什么,然后进行强制转换
    				//这样才可以确定输出的是bugNum 还是 ProjectNum
    				
    				//如果判断是programmer类型的,就要强制转换,才能得到bugNum
    				if(emp instanceof Programmer) {
    					//强制转换
    					Programmer pg = (Programmer)emp;
    					//输出BugNu
    					//只有pg才能点出来BugNu
    					System.out.println(pg.getBugNum());
    				}
    				
    				//如果判断是ProjectManager类型的,就要强制转换,才能得到ProjectNum
    				if(emp instanceof ProjectManager) {
    					//强制转换
    					ProjectManager pm = (ProjectManager)emp;
    					//输出ProjectNum
    					//只有pm才能点出来ProjectNum
    					System.out.println(pm.getProjectNum());
    				}
    				
    				System.out.println("");
    			}
    		}
    	}
    }
    
    //删除员工方法
    //-------------------------------------------------------------------------------
    
    public void deleteEmp() {
    	System.out.println("请输入要删除的员工编号");
    	//Scanner 接收要删除的编号
    	String id = input.next();
    	//首先定义一个flag 为false  来判断是否能删除成功
    	boolean flag = false;
    	//for循环遍历 来判断名字
    	for(int i=0;i<arry.length;i++) {
    		//因为是String所以用.equals来判断
    		if(arry[i].getId().equals(id)) {
    			//首先把flag定义为true来判断接下来的删除了没有
    			flag = true;
    			//将数组arry[i]元素的值赋值为空 就代表 删除了
    			arry[i] = null;
    			//跳出循环
    			break;
    		}
    	}
    	
    	//如果删除了flag的值在上边就会变为true
    	if(flag == true) {
    		System.out.println("删除员工信息成功");
    		//没删除成功flag依旧是一开始定义的false
    	}else if(flag == false) {
    		System.out.println("没有找到要删除的员工");
    	}
    }
}
package com.project.javaempsys;

public class test {

	public static void main(String[] args) {
		//new Meneu对象 输出功能
		Menue menue = new Menue();
        menue.printMeneu();
	}

}


3、多态

在生活当中我们看待一件事有很多不同的状态,假如一个男人 儿子看他就是父亲,父亲看他就是儿子,妻子看他就是丈夫,

在我们程序当中,也是有相似的情况,对于这种情况我们称之为多态,是指属性和方法在子类当中 表现为多种形态,假如说一个Pet类 有一个pig类继承了他,那么new之后的一个pig对象就即是pig又是Pet

多态是对方法而言的

同一父类类型,不同的子类对象,对父类的同一方法,表现出不同的状态

概念:父类引用指向子类对象,从而产生多种形态

 两种表现形式:           父类   变量名 = new 子类();     (上边的综合案例)

                                      方法调用                                 (下边的案例)


所以说,多态只有在直接或间接继承关系之中才会体现出来。

父类引用后仅可以调用父类的对象和方法,不可以调用子类独有的属性和方法

如果子类重写了父类中的方法,执行子类中重写后的方法,否则执行父类的方法


1、多态的应用场景

使用父类作为方法形参实现多态,使方法参数的类型更为广泛

使用父类作为方法返回值实现多态,是方法可以返回不同的子类对象

多态的实现方式其实就是方法的重写。

三种方式   父类做类型 new 子类对象   在instanceof后 父类变量名. 后 有父子类两个的属性(有子类证明运用到了多态)

                 参数做类型  传入父类的参数,传递的是子类的参数对象

                 方法的返回值是父类类型,具体返回的是子类对象

参数的  父类定义一个方法

              两个子类继承方法

              再单独写一个类A 可继承可不继承

              类A里有个方法,

这个方法里的行参参数是父类类型的,想输出子类的共有属性,也就是父类 属性子类new赋值之后就直接父类 . 就可以,根据重写原则,输出的一定是子类,当然在这个方法里调用一个父类的方法,在这个方法被子类重写之后,new类A里的方法,然后就会把所有重写过父类方法的子类里的这个方法全输出出来

例题

我们首先定义一个父类  再定义两个子类来继承,再定义一个单独的输出两个子类的类,这个类不继承父类,如果我想输出两个子类的方法那么我的这个单独的类就必须得分别写两个对用子类的方法,这是两个,如果写100个,1000个呢?我们不可能写那么多,有没有办法就写一个方法,然后就可以把所有子类的方法全都调用出来呢?  在这里我们就可以运用多态来进行

父类

public class Pet {
	//公共属性名字
	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//定义一个方法,然后在子类重写
	public void eat(String food) {
		System.out.println("宠物" + this.name + "正在吃" + food);
	}
}

第一个子类

public class Pig extends Pet{
	public void eat(String food) {
		System.out.println("我是宠物" + super.getName() + "正在吃主人投喂的" + food);
	}
}

第二个子类

public class Peguin extends Pet{
	public void eat(String food) {
		System.out.println("我是宠物" + super.getName() + "正在吃主人给的" + food);
	}
}

调用这两个子类的类

//不运用多态

public class Master {
	
	主人名字
	private String name;
	
	//写一个主人的声明方法
	public void feed(Pig pig,String str) {
		System.out.println("我是主人" + this.name+"正在喂养宠物"+pig.getName());
		//直接传pig的吃的方法
		pig.eat(str);
	}
	
	public void feed(Peguin peguin,String str) {
		System.out.println("我是主人" + this.name+"正在喂养宠物"+peguin.getName());
		//直接传peguin的吃的方法
		peguin.eat(str);
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

因为我想输出两个方法所以这里边我就要写两个方法,要是100个 1000个 那我们不能写100个

或者1000个,就得想办法写一个就把所有的放法调用出来

//运用多态

public class Master {
	
	主人名字
	private String name;
	
	//写一个主人的声明方法
	public void feed(Pet pet,String str) {
		System.out.println("我是主人" + this.name+"正在喂养宠物"+pet.getName());
		//eat方法是子类重写的
		//str是eat方法里的食物
		pet.eat(str);
	}
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

把传进去的参数从子类变成了父类,调用了父类的eat方法,当执行的时候,父类自己就会去检查子类有没有方法重写,有的话,输出子类的eat方法,没有的话,输出父类的eat方法

输出类

public class Demo1 {
	public static void main(String[] args) {
		//必须先new子类Pig
	    Pig peiqi = new Pig();
	    //通过构造器赋值
	    peiqi.setName("佩奇");
	    
	    //必须先new子类Peguin
	    Peguin qq = new Peguin();
	    //通过构造器赋值
	    qq.setName("QQ");
	    
	    //把这个单独的不继承父类的类new出来
	    Master jiaBao = new Master();
	    //给其赋值名字
	    jiaBao.setName("张三");
	    
	    //把这个单独的不继承父类的类new出来
	    Master haoTian = new Master();
	    //给其赋值名字
	    haoTian.setName("李四");
	    
	    //定义名字输出
	    jiaBao.feed(peiqi, "饲料");
	    haoTian.feed(qq, "大虾");
	    
	    
	}
}

 结果

 


向上转型(装箱)

父类   变量名 = new 子类();  --------->    如果子类重写了父类的方法 new时调用父类会自动

                                                              调用子类的方法

子类可以自动转换为父类

LSP : 里氏代换原则 任何父类类型出现的地方,都可以使用子类对象进行替换

【注意】子类独有成员无法访问

向下转型(拆箱)

运用 instanceof 关键字

在使用instanceof之前我们要先进行 if 判断,判断要进行转换的这个类也就是父类的原始类是什么类

if(要转换的类 instanceof 原始类)

进行强制类型转换   原始类  变量名  =  (原始类)要转换的类

也就是说当父类类型 new 子类对象之后 使用instanceof就可以访问子类的东西了,要是不使用instanceof就只能访问父类类型中的东西

public class Test3 {
	public static void main(String[] args) {
		Test1 t = new Test2();

	
		if (t instanceof Test2) {
			Test2 t2 = (Test2) t;
			System.out.println(t2.Test2Main());
		}
		
	}
}


2、多态的作用

屏蔽子类间的差异

灵活、耦合度低


3、面试题

多态的实现方式有几种?有什么区别?

有两种实现方式

1、方法重写实现多态

2、方法重载实现多态

区别

方法重载实现多态,属于静态方式实现多态,在编译的时候,重载的方法就已经被编译、确定

父类写很多个同名不同参的方法   --------------------->   子类调用这个方法里边写不一样的东西自动                                                                                        找子类

方法重写实现多态,属于动态方式实现多态,在编译时,子类的方法并没有覆盖掉父类中的方法,而是在调用时,使用哪个子类对象调用,这时这个子类的方法才覆盖掉,重写了父类的方法

每一个子类都重写父类的方法,调用父类子类方法将其覆盖,输出的是子类的方法


一定要先继承有父类和子类的关系

再用父类.方法 子类如果有重写,自己就去调用子类的方法了

父类一定要有方法,因为变量名 . 用的是父类的类型的,如果父类的虚方法没有了,那么就 . 不出来这个方法了,那么更别提会自动找子类这个事了

父类 变量名 = new 子类

变量名.的都是父类的方法  如果子类当中重写了父类的方法,那就调用子类方法

子类里不能重写父类构造器,也不也能重写父类的static方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值