Java学习之Java的基本语法3

1.上节课知识点回顾

编程语言 (1).png

2. Java继承

这是两个类,一个是Manager类,一个是Worker类

package com.lx.chapter4;

public class Manager {
	
	//姓名
	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;
	}

}

package com.lx.chapter4;

public class Worker {

	// 姓名
	private String name;

	// 年龄
	private int age;

	public Worker(String name, int age) {

		this.name = name;
		this.age = age;
	}

	public Worker() {

		// TODO Auto-generated constructor stub
	}

	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;
	}

}

我们可以发现到,两个类的代码极度的相似。

在一些场景下,进行大规模开发中,如果出现这种代码,那么到最后我们的文件一定是非常臃肿且难以维护的。

此时就需要我们的另一种Java的功能来对代码进行优化

package com.lx.chapter5;

//java的角度,把各个类的相同的变量和方法抽取到:父类中
//java的继承的作用就是:减少各个子类中相同的变量和方法,这是优化和设计,extends继承关键字可以提升性能。

//抽象: abstract、interface:作用:就是为了加强多态

public class Employee {
	
	//姓名
	 String name ;
	
	//年龄
     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;
	}

}
package com.lx.chapter5;

public class Worker  extends  Manager {
	
	
	public static void main(String[] args) {
		
		Manager  m = new Manager();
		m.name ="子类Manager";
		
		System.out.println(m.getName());
		
		
		Worker  w  = new Worker();
		w.age  =100;
		System.out.println(w.getAge());
		
	}

}

所有的类都继承一个类Object,Object是所有类的父类

package com.lx.chapter6;

//java中的类都是继承于父类,继承两种:
// 1. 直接继承(写extends,直接的父类是extends右边的类,顶级的父类一定是Object) 
//2.间接继承(如果没有写extends,一定继承Object)
public class Stu {
	
	public static void main(String[] args) {
		
		//System.out.println(this.hasCode());
	
		Stu  s   = new Stu();
		
//这个Stu类中没有定义hashCode()方法,查看这个hasCode方法,
//可以发现该方法来自Object,又证明了所有类都继承Object而成的类
		System.out.println(s.hashCode());
	}
  
}
Tips

继承有传递性,Worker直接的父类是Manager,间接的顶级父类是Object

Object类是所有类的顶级父类

java在继承的设计中,不同于C++(支持多继承,没有自动垃圾回收机制),

单继承(高斯林设计,减少类的复杂度,直接继承一个父类),但是可以通过父类继承另一个父类让子类来获得两个父类的属性,从而达到继承两个类的功能

package com.lx.chapter6;



public class Worker   extends  Emp{
	
	public static void main(String[] args) {
		
		Worker  w = new Worker();
		System.out.println(w.hashCode());
		
	}

}

3.修饰符访问限制

protected 受保护,其他类无法直接访问,但是由其他类继承的子类可以访问该属性

缺省default,同一个包的子类可以直接访问,不同包不可以直接访问

private 私有 子类不能直接访问,通过set/get方法访问

public不同包下的子类也可以直接访问

package com.lx.chapter7;


public class Person {
	//访问修饰符的可访问的范围
	//public>protected>default>private 
	protected  int  count  = 10;
}

例1:

Student类

package com.lx.chapter7;

public class Student   extends   Person{

	
	
	public static void main(String[] args) {
		
		Student  s   = new  Student();
		System.out.println(s.getClass());
		
		System.out.println(s.count);
	}
}

Teacher类

package com.lx.chapter8;

import com.lx.chapter7.Person;

public class Teacher extends   Person{
	
	public  void  showInfo()
	{
		Teacher  t  = new Teacher();
		System.out.println(t.count);
		
	}

}

Person类

package com.lx.chapter9;

public class Person {
	
	int count  =10 ;

}

student类和Teacher类都继承person

子类student和Teacher可以调用父类person的count属性

person中的count缺省,故可以直接访问

4.重写(Override)

Stu类

package com.lx.chapter9;

//java书:父类中的所有变量和方法都被子类继承。

public class Stu   extends Person{
	
	//当子类出现和父类同名的同类型的变量,父类的同名变量是否被子类继承?
	int count  = 20 ;
	
	public static void main(String[] args) {
		Person  p  = new Person();
		System.out.println(p.count);
		Stu  s   =new Stu();
		System.out.println(s.count);
	}

}

可以看到当子类出现和父类同名的同类型的变量,子类会重写父类的属性值。

重写(Override)

从字面上看,重写就是 重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,所以在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。但要注意子类函数的访问修饰权限不能少于父类的。

5.继承与静态变量问题

将Person,Student类中的count属性设置为静态

package com.lx.chapter10;

public class Person {
	
	static int count  =10;

}

Student类

package com.lx.chapter10;

public class Student   extends Person{
	
	static int count  =100;
	
	public static void main(String[] args) {
		
		System.out.println(Student.count);
      //易错点:静态内存的存放方式
		Student.count  =100;
		System.out.println(Person.count);
	}

}

问:两次输出的结果是什么


答案:第一次输出是:100,第二次输出为10

static属于一个独立的内存,各个对象都可以去访问,被static修饰的变量或者方法不会被子类的相同属性的修改而变化。静态变量只能通过static关键字进行调用访问。

如上例子中,Person的count,就写在了静态内存,你只能通过static关键字进行调用修改,换句话来说就是只能通过Person.count来调用修改。当子类拥有与父类相同的属性名而子类的属性值不同而被重写时,用static关键字修饰的方法不受影响,进而不会被重写。

6.super()&this()关键字

super()关键字,调用父类的构造函数

this()关键字,调用当前类的构造函数

package com.lixin.chapter11;

public class Base {
	
	public  Base()
	{
		
	}
	
	public Base(int a)
	{
		System.out.println("父类Base的构造函数");
	}
	
	

}

Son类

package com.lixin.chapter11;

//子类的构造函数一定必须依赖于父类的构造函数
//先有爸爸,才有儿子


public class Son  extends  Base{
	
	//隐式的依赖
	public Son()
	{
		//super(10);
		//this(20);
	}
	
	public Son(int a)
	{
		super(a);
	}
	
	public static void main(String[] args) {
		
		Son  s = new Son();
	}
	

}

问: 程序会输出什么?

tips:

直接的 间接的 = 继承

隐式的 显示的 = 依赖

1. 如果父类提供的构造函数是默认无参构造函数

子类构造函数可以使用super显示的或隐式的调用

2. 如果父类提供的构造函数是有参构造函数

子类构造函数一定要使用super显示的调用有相同参数的父类构造函数

super() 必须在第一行。

super()和this()不能同时出现

子类构造函数到底怎么去依赖父类的构造函数:

取决于父类提供什么样的构造函数。

你想依赖父类提供的哪个构造函数

答案:父类Base的构造函数

7.介绍控制反转,依赖注入:

Base类

package com.lixin.chapter14;

public class Base {

}

Son1类

package com.lixin.chapter14;

public class Son1   extends Base{

}

Son2类

package com.lixin.chapter14;

public class Son2   extends Base{

}

Test类

package com.lixin.chapter14;

public class Test {
	
	public static void main(String[] args) {
		//spring最核心的思想依赖注入,控制反转
		
		//一个父类指向多个子类的机制
		
		//创建对象的控制权由代码的本身来创建,反过来,转移给由容器根据xml或注解来创建对象
		//Base  base   =  new   Son1(); // 固定死了,绑定死了  编译期间
		
		//程序目前给出的吃饭,代码能表现出来吗,具体吃什么?也就是在编译期间能给出吃饭,具体吃什么?不能
		//在程序运行期间,给出吃饭具体去吃什么?
		//依赖注入,在程序运行期间,根据用户的需要注入相对应的对象,体现灵活性。
		//依赖注入 == 控制反转
		//Base  base   = Application.getName("吃饭"); //吃饭是什么  运行期间
		
	}

}

再审:static修饰的方法名相同,参数列表相同,返回值类型相同,static修饰的是方法,是类方法,是属于每个类的,不属于哪个对象,所以不是方法重写。

package com.lx.demo11;

public class Base {
	
	public static void add()
	{
		System.out.println("Base类的add方法");
	}

}

package com.lx.demo11;

public class Son extends Base{
	
	public static void add()
	{
		System.out.println("Son类的add方法");
	}
	
	public static void main(String[] args) {
		
		
		Base   b  = new Son();
		b.add();
	}

}

M