构造函数
class Student{
String stuName;
public Student(){
System.out.println("无参构造函数");
}
public Student(String name){
System.out.println("带参的构造函数");
this.stuName = name;
//System.out.println("name ="+);
}
}
class Demo{
public static void main(String[] args){
System.out.println("无参");
//创建(实例化)无参的对象调用类中的无参构造函数
Student stu1 = new Student();
System.out.println("----------------");
System.out.println("带参构造函数");
//创建(实例化)带参的对象调用类中的含参构造函数
Student stu2 = new Student("刘德华");
System.out.println("name = "+stu2.stuName);
}
}
构造函数的私有化
作用
- 像这种只提供功能性方法的类,包含的全部都是static的方法,这样的类一般不需要实例化,通过类名就可以访问成员属性,所以,可以将此类的构造函数设为私有的,外部不能实例化;
class MyMath{
private MyMath(){
System.out.println("私有化构造函数");//私有的不能实例化,同时也不会运行到这一步
}
public static int getMax(int a , int b){
return a > b ? a : b;
}
public static int getMin(int a , int b){
return a < b ? a : b;
}
}
class Demo{
public static void main(String[] args){
//MyMath m = new MyMath();编译错误,私有的构造函数不能实例化
System.out.println(MyMath.getMax(10,20));
System.out.println(MyMath.getMin(10,20));
}
}
- 例模式:在我们的整个应用程序运行期间,只需要一个某个类的对象,这时,我们可以将此类设计为”单例模式”,整个应用程序运行期间,只有一个对象存在
步骤:
1.将此类的构造器设为私有;
2.提供一个私有的属性,这个属性是这个类的一个对象;
3.提供一个公有的静态方法,返回这个私有属性
class Student2{
//私有静态属性:
//作用:提供给内部的静态的方法访问
private static Student2 stuObj = new Student2();
private Student2(){
}
public static Student2 getStudentInstance(){
return stuObj;
}
}
继承
- 类中出现重复的属性定义
- 继承之后,子类将拥有父类中允许被继承的成员(属性和方法)(父类中的私有private属性、方法不能被子类继承)
- 代码复用
- 继承是一种可以访问的权限,并不是真正拥有父类的成员属性和成员方法
- java不支持多继承,但是支持多级继承
多继承
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2…//error
多级继承
class A{}
class B extends A{}
class C extends B{}
class A{//父类
String name;
char sex;
int age;
public void show(){
System.out.println("我叫:" + name + ",性别:" + sex + ",年龄:" + age);
}
}
class C extends A{//子类
String stuNo;//学员编号
}
class Demo{
public static void main(String[] args){
C stu = new C();
stu.stuNo = "00001";
stu.name = "张学友";
stu.sex = '男';
stu.age = 30;
stu.show();
// System.out.println(stu.name + "," + stu.sex + " , " + stu.age);
}
}
子类的实例化过程
class Personnel{
private int num = 10;//父类中私有的东西,不能被继承
Personnel(){
System.out.println("父类构造函数");
}
String name= "Personnel";
int age;
}
class Student extends Personnel{
private int num = 20;//子类中也定义一个同父类中相同的私有的变量。被认为是子类自己的成员变量
Student(){
/*
*子类中所有的构造函数默认都会访问父类中空参数的构造函数,
*因为每一个构造函数的第一行都有一条默认的语句super();
*/
super();
System.out.println("子类构造函数");
}
String stuNo;
String name = "Student";
public void show(){
System.out.println("name = " + name);//Student
System.out.println("父类的name = " + super.name);//Personnel
System.out.println("试图调用父类中私有的num变量 = " + num);//如果子类也有num,将访问子类的num
}
}
class Demo
{
public static void main(String[] args)
{
Student stu = new Student();
stu.show();
}
}
继承时super和this关键字的使用
- this关键字代表本类对象的引用
- super关键字代表父类内存空间的标识,只能在子类中调用父类对象时使用
class Demo{
public static void main(String[] args){
B b = new B();
b.show();
}
}
class A{
int num =10;
}
class B extends A{
int num = 20;
public void show(){
int num = 30;
System.out.println("num="+num);//调用局部变量中的num
System.out.println("this.num=" +this.num);//调用本类中的num变量
System.out.println("super.num="+super.num);//调用父类中的num变量
}
}
方法(函数)的重写
函数的重写(Override)
1.子类的方法与父类的方法必须完全相同的: 返回值类型 方法名 参数列表
2.访问修饰符:子类必须拥有同父类相同或者更宽的访问修饰符
class Demo{
public static void main(String[] args){
B b = new B();
b.show("小明",20);
}
}
class A{
public void show(String name,int age){
System.out.println("A.show()");
}
}
class B extends A{
public void show(String name,int age){
super.show(name,age);//在子类中可以访问被覆盖的父类的方法,可以不在第一行
System.out.println("B.show()");
}
}
多态
前提:
- 需要存在继承或者实现关系
- 要有覆盖操作
成员变量:
- 如果父类有,子类没有:访问的是父类的
- 如果父类有,子类也有个相同的:访问的是父类的
- 如果父类没有,子类有:编译错误
多态时,访问的成员变量,父类必须要有,否则编译错误。而且运行时访问的是父类的
成员方法:
- 如果父类有,子类没有:访问的是父类的
- 如果父类有,子类重写:访问的是子类的
- 如果父类没有,子类有:编译错误
多态时,对于重写的方法:执行期动态绑定到子类的方法,所以执行时执行的是子类。编译时,要求父类必须要有,如果没有,编译错误;编译时看父类,运行时运行的是子类的
静态的成员方法:
- 如果父类有,子类没有:访问的是父类的
- 如果父类有,子类重写:访问的是父类的
- 如果父类没有,子类有:编译错误
class A{
public int num = 10;
public static void run(){
System.out.println("A的run方法");
}
public void show(){
System.out.println("A的show方法");
}
}
class B extends A{
public int num = 20;
public static void run(){
System.out.println("B的run方法");
}
public void show(){
System.out.println("B的show方法");
}
}
class Demo{
public static void main(String[] args) {
A c = new B();//创建了一个A类型(父类),使用的是子类的空间
System.out.println(c.num);//打印 10
c.run();//打印 A的run方法
c.show();//打印 B的show方法
}
}
当父类引用指向子类对象时,访问的成员属性和成员方法:
- 编译时:父类必须要有,否则编译错误
- 运行时:成员属性和静态方法都是父类的,只有重写的成员方法运行时是运行的子类的
- 多态时,父类的引用不能访问到子类自有的方法