黑马程序员——java中构造函数、继承、多态、接口总结

------ Java培训、Android培训 、期待与您交流! -------

一、构造函数

     1、概念和作用
          构造函数是构建创造对象时调用的函数。构造函数可以给对象进行初始化。在主函数中创建对象时必须要通过构造函数进行初始化。一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数。另外也可以在类中定义了指定的构造函数,此时创建对象时调用的是自定义的构造函数。
     2、构造函数和一般函数的区别
          构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。对象创建时,会调用只调用一次。没返回值
          一般函数:对象创建后,需要函数功能时才调用。 对象创建后,可以被调用多次。有返回值
     3、构造函数的重载
         在 Java 里,不仅一般函数可以重载,构造函数也可以重载。只要构造函数的参数个数不同,或是类型不同,便可定义多个名称相同的构造函数。
//构造函数重载
class Person {
	private String name;
	private int age;

	public Person() {//空参数构造函数
	}

	Person(String n, int a) {//带有两个参数的构造函数
		name = n;
		age = a;
	}

	public String talk() {
		return "我是: " + name + ",今年: " + age + "岁 ";
	}
}

public class Construct {
	public static void main(String[] args) {
		Person p = new Person();//调用空参数构造函数
		System.out.println(p.talk());//打印姓名和年龄
		Person p1 = new Person("小明",20);//调用有参数构造函数并传入参数
		System.out.println(p1.talk());//打印姓名和年龄
	}
}

输出结果为:
我是: null,今年: 0岁      
我是: 小明,今年: 20岁
由结果可以看出:构造函数中String类型默认初始化值为null,int类型默认初始化值为0。

    4、this关键字

class Person {
	String name;
	int age;

	public Person() {
		System.out.println("1. public Person()");
	}

	public Person(String name, int age) {
		this();// 调用本类中无参构造方法,即Person(){},必须定义在构造函数的第一行
		this.name = name;//this表示当前对象
		this.age = age;//this表示当前对象
		System.out.println("2. public Person(String name,int age)");
	}
}

public class TestThis {
	public static void main(String[] args) {
		new Person("小明", 20);
	}
}

输出结果为:

1. public Person()
2. public Person(String name,int age)

          由此可见,this关键字可以表示当前对象,也可以在构造函数中调用另一个构造函数。


     5、static关键字

class Person {
	String name;
	private static String city = "北京";// 静态变量被所有对象共享
	int age;

	public Person() {
		System.out.println("1.public Person()");
	}

	// 此段代码会首先被执行——静态代码块
	static {
		System.out.println("2.Person 类的静态代码块被调用! ");
	}

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String talk() {
		return "我是:" + this.name + ",今年:" + this.age + "岁,来自:" + city;
	}

	// 静态方法定义的内容可以用于非静态和静态方法中使用
	// 静态方法中使用非静态方法中的内容时会报错
	public static void setCity(String c) {
		city = c;
	}
}

public class TestStatic {
	// 运行本程序时,静态代码块会被自动执行
	static {
		System.out.println("3.TestStatic 类的静态代码块被调用! ");
	}

	public static void main(String[] args) {
		System.out.println("4.程序开始执行! ");
		// 产生两个实例化对象
		Person p1 = new Person("小明", 25);
		Person p2 = new Person("小红", 23);
		System.out.println("修改之前信息: " + p1.talk());
		System.out.println("修改之前信息: " + p2.talk());
		System.out.println(" **************修改之后信息**************");
		// 修改后的信息
		Person.setCity("上海");// 静态方法可以用类名直接调用
		System.out.println("修改之后信息: " + p1.talk());
		System.out.println("修改之后信息: " + p2.talk());
	}
}

输出结果为:

3.TestStatic 类的静态代码块被调用! 
4.程序开始执行! 
2.Person 类的静态代码块被调用! 
修改之前信息: 我是:小明,今年:25岁,来自:北京
修改之前信息: 我是:小红,今年:23岁,来自:北京
 **************修改之后信息**************
修改之后信息: 我是:小明,今年:25岁,来自:上海
修改之后信息: 我是:小红,今年:23岁,来自:上海

         由以上程序可以得出,static关键字可以用于修饰变量、方法和代码块。静态变量被所有对象共享。静态方法中不可以使用非静态内容,当函数功能没有访问到对象的特有内容时就可以定义为静态。静态代码块用于给类进行初始化,会先执行。


     6、内部类

         分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。这时就是还有的事物定义成内部类来描述。内部类可以直接访问外部类中的成员。外部类要访问内部类,必须建立内部类的对象。

//内部类总结
class Outer {
	int score = 95;

	// 外部类可以访问内部类中的成员,内部类持有了外部类的引用: 外部类名.this
	void inst() {
		Inner in = new Inner();
		in.display();
	}

	// 内部类在局部位置上只能访问局部中被final修饰的局部变量。
	void inst1(final int s) {
		final int temp = 20;
		class Inner1 {
			void show() {
				System.out.println("成绩1:score=" + (score + s + temp));
			}
		}
		Inner1 in = new Inner1();
		in.show();
	}

	// static class Inner{}
	// 用 static 声明的内部类则变成外部类,但是用 static 声明的内部类不能访问非 static 的外部类属性
	public class Inner {
		void display() {
			// 在内部类中声明一name属性
			// String name = "小明";
			System.out.println("成绩: score = " + score);// Outer.this.score
		}

		// static void function(){//如果内部类中定义了静态成员,该内部类也必须是静态的。
		// System.out.println("function run ...."+score); }

	}

	// 在此调用内部类的name属性,会产生错误,外部类不能访问内部类中的属性 public void print(){
	// System.out.println("姓名:"+name); }

}

public class InnerClassDemo {
	public static void main(String[] args) {
		Outer out = new Outer();
		out.inst();
		// 直接访问外部类中的内部类中的成员。
		Outer.Inner in = new Outer().new Inner();
		in.display();

		// 如果内部类是静态的。 相当于一个外部类
		// Outer.Inner in = new Outer.Inner();
		// in.display();

		// 如果内部类是静态的,成员是静态的。
		// Outer.Inner.function();
		out.inst1(5);
	}
}

输出结果为:

成绩: score = 95
成绩: score = 95
成绩1:score=120          


二、继  承

     1、继承相关概念

         java中继承用到extends关键字。当类与类之间存在着所属关系(is-a)时,就定义继承。被继承的类成为父类或超类,继承得到的新类成为子类或派生类。父类是子类不断向上抽取出来的。如:class Students(子类) extends Person(父类)。子类会继承父类的所有属性和方法。

         java中不允许多继承,即一个子类不允许有多个父类。但是允许多层继承,即C继承B,B继承A,就出现了继承体系。

    2、子类继承父类的特性

        2.1  子类实例化

一个对象实例化过程:

Person p = new Person();

  • JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况下);
  • 在堆内存中的开辟空间,分配地址;
  • 并在对象空间中,对对象中的属性进行默认初始化;
  • 调用对应的构造函数进行初始化;
  • 在构造函数中,第一行会先到调用父类中构造函数进行初始化;
  • 父类初始化完毕后,在对子类的属性进行显示初始化;
  • 在进行子类构造函数的特定初始化;
  • 初始化完毕后,将地址值赋值给引用变量。

        2.2  super关键字:用于子类中,调用父类中的构造方法,此时只能放在子类程序的第一行。另外可以通过(super.父类中的属性或方法)来调用父类的内容。但是子类不能访问父类中的私有内容。super关键字与this关键字调用构造函数的操作是不能同时出现的。

        2.3  覆盖

        当子父类中出现成员函数一模一样的情况,会运行子类的函数。这种现象,称为覆盖操作。当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就使用覆盖操作完成。这时函数在子父类中的的两个特性:

  • 重载。同一个类中。overload
  • 覆盖。子类中。覆盖也称为重写,覆写。override
当子类覆盖父类中的内容时,需要注意的是:子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限,并且静态内容只能覆盖静态内容,或被静态内容覆盖。


//继承总结
class Person {
	String name;
	int age;

	// 父类中构造函数
	public Person() {
		System.out.println("1.public Person(){}");
	}

	// 父类中构造函数
	public Person(String name, int age) {
		// this关键字代表当前对象
		this.name = name;
		this.age = age;
	}

	// 父类中的方法
	public String talk() {
		// this调用本类中的内容
		return "我是: " + this.name + ",今年: " + this.age + "岁 ";
	}
}

// Student类继承于Person类
class Student extends Person {
	String school;

	// 子类中的构造函数
	public Student() {
		// super();隐含super调用父类中的空参数构造函数
		System.out.println("2.public Student(){}");
	}

	public Student(String name, int age, String school) {
		// 分别为属性赋值
		this.name = name;
		this.age = age;
		this.school = school;
	}

	// 此处复写 Person 类中的 talk()方法,并用super调用父类中的talk方法
	public String talk() {
		return super.talk() + ",我在" + this.school + "上学";
	}
}

class ExtendsDemo2 {
	public static void main(String[] args) {
		Student s = new Student();
		Student ss = new Student("小明", 23, "北京");
		// 此时调用的是子类中的 talk()方法
		System.out.println(ss.talk());
	}
}

输出结果为:

1.public Person(){}
2.public Student(){}
1.public Person(){}
我是: 小明,今年: 23岁 ,我在北京上学


三、抽象类

     

    抽象类定义规则

  •  抽象类和抽象方法都必须用 abstract 关键字来修饰。
  •  抽象类不能被实例化,也就是不能用 new 关键字去产生对象。
  •  抽象方法只需声明,而不需实现。
  •  含有抽象方法的类必须被声明为抽象类,抽象类的子类必须复写所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。

//抽象类
abstract class Person {
	String name;
	int age;
	String occupation;

	//抽象类中定义构造函数
	public Person(String name, int age, String occupation) {
		this.name = name;
		this.age = age;
		this.occupation = occupation;
	}

	// 定义抽象方法 talk()
	public abstract String talk();
}

// Student 类继承自 Person 类
class Student extends Person {
	public Student(String name, int age, String occupation) {
		//调用抽象类中的构造函数
		super(name, age, occupation);
	}

	//覆盖 talk()方法
	public String talk() {
		return "学生的姓名: " + this.name + ",年龄: " + this.age + ",职业:"
				+ this.occupation + "! ";
	}
}

// Worker 类继承自 Person 类
class Worker extends Person {
	public Worker(String name, int age, String occupation) {
		//调用抽象类中的构造函数
		super(name, age, occupation);
	}

	// 覆盖 talk()方法
	public String talk() {
		return "工人的姓名: " + this.name + ",年龄: " + this.age + ",职业:"
				+ this.occupation + "! ";
	}
}

class AbstractDemo {
	public static void main(String[] args) {
		Student s = new Student("小明", 20, "学生");//创建Student对象
		Worker w = new Worker("小强", 28, "工人");//创建Worker对象
		System.out.println(s.talk());//调用的方法
		System.out.println(w.talk());//调用的方法
	}
}


 

输出结果为:

学生的姓名: 小明,年龄: 20,职业:学生! 工人的姓名: 小强,年龄: 28,职业:工人! 

四、接  口

    当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是 接口( interface)。接口里的数据成员必须初始化,且数据成员均为常量。接口里的方法必须全部声明为 abstract,也就是说,接口不能像抽象类一样有一般方法,而必须全部是“抽象方法”。对于接口当中的成员都有固定的修饰符。全局常量: public  static final ;抽象方法。public abstract。接口是java实现多继承的一种机制,它可以通过多实现来达到多继承的效果。

//定义接口
interface A {
	int i = 10;//public static final int i = 10;

	public void sayI();//public abstract void sayI();
}

interface E {
	int x = 40;

	public void sayE();
}

// B 同时继承了 A、 E 两个接口
interface B extends A, E {
	int j = 20;

	public void sayJ();
}

// C 继承实现 B 接口,也就意味着要实现 A、 B、 E 三个接口的抽象方法
class C implements B {
	public void sayI() {
		System.out.println("i = " + i);
	}

	public void sayJ() {
		System.out.println("j = " + j);
	}

	public void sayE() {
		System.out.println("e = " + x);
	}
}

class InterfaceDemo {
	public static void main(String[] args) {
		C c = new C();
		c.sayI();
		c.sayJ();
		c.sayE();
	}
}

输出结果为:

i = 10
j = 20
e = 40


五、多  态

     一个对象对应着不同类型即为多态。如动物对象里有猫和狗两种形态。在java中多态体现在父类或接口的引用指向其子类对象。多态的存在提高了代码的扩展性,但是使用多态后前期定义的内容不能使用(调用)后期子类的特有内容。多态涉及两个转型:向上转型和向下转型。向上转型会自动完成,向下转型需要进行强制类型转换。


//定义多态
abstract class Person {
	abstract void talk();

}

//American类继承Person类
class American extends Person {
	void talk() {
		System.out.println("说英语");
	}

	void playbasketball() {
		System.out.println("打篮球");
	}
}

//Japanese类继承Person类
class Japanese extends Person {
	void talk() {
		System.out.println("说日语");
	}

	void tea() {
		System.out.println("喝茶");
	}
}

class DuoTaiDemo {
	public static void main(String[] args) {

		Person a = new American(); // 向上转型,隐藏子类的特有内容。。

		American c = (American) a;// 向下转型的目的是为了使用子类中的特有方法。
		c.talk();
		c.playbasketball();

		// 对于转型,自始自终都是子类对象在做着类型的变化。
		// Person a1 = new Japanese();
		// Japanese c1 = (Japanese)a1;//ClassCastException
		
		method(new Japanese());

	}

	public static void method(Person p) {
		p.talk();

		// instanceof:用于判断对象的具体类型。只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。
		if (p instanceof American) {
			American a = (American) p;
			a.playbasketball();
		} else if (p instanceof Japanese) {
			Japanese j = (Japanese) p;
			j.tea();
		} else {

		}

	}
}

输出结果为:

说英语
打篮球
说日语
喝茶





------ Java培训、Android培训 、期待与您交流! -------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值