Java的基本语法3
Java学习之Java的基本语法3
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;
}
}
我们可以发现到,两个类的代码极度的相似。
.png)
在一些场景下,进行大规模开发中,如果出现这种代码,那么到最后我们的文件一定是非常臃肿且难以维护的。
此时就需要我们的另一种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