构造方法
用于创建对象并初始化对象属性的方法叫“构造方法”,也叫构造器,在类中定义,分为无参和有参;
- 构造器的名称必须和类名相同,包括大小写;
- 构造器没有返回值,不能写void、return;
- 用“new”调用,且对象一建立,构造器就会运行,并且只运行一次;
- 如果类没有声明任何的构造器,Java编译器会默认提供一个无参构造器,当声明了构造器,默认的构造器就会失效;
- 已经声明了一个构造器切这个自定义的构造器是有参的那么默认的无参构造器失效切不能被调用;
public class Demo{
public static void main(String[] args){
A a = new A();//new一个对象,调用了A中的无参构造器;
B b = new B();//编译出错,B已经定义了一个有参构造器,默认的无参构造构造器失效
}
}
class A{}
class B{
//声明一个有参构造方法
public B(String s1){
System.out.orintln(s1);
}
}
所以在自定义构造器的时候一定要手动写一个无参构造器,防止发生错误;
- 构造器不能被继承,子类构造器默认调用父类型的无参构造器;
- 子类构造器一定要调用父类构造器,如果父类没有无参构造器,则必须使用super(有参数),来调用父类有参的构造器,那么为什么子类一定要访问父类的构造器?因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问一下父类中的构造器;
总之,子类中至少会有一个构造器会访问父类中的构造器,且子类中每一个构造方法中的第一行都有一句隐式super();
构造代码块
每次实例化对象时,构造代码块一定会执行,且在构造方法前执行;
静态构造代码块:在类加载时执行,第一次实例化对象时执行类加载;
public class Demo{
//静态构造代码块
static {
System.out.println("执行静态构造代码块");
}
//构造代码块
{
System.out.println("执行构造代码块");
}
//无参构造器
public Demo(){
System.out.println("执行无参构造器");
};
//有参构造器
public Demo(int i){
System.out.println("执行有参构造器"+i);
}
//程序入口;
public static void main(){
new Demo();
new Demo(1);
}
}
super()、super. 和this()、this.
this. :
- this:指代当前对象,实例化谁就是指代谁;
- 在普通方法中获取属性或者方法;
- 如果访问当前对象,本类对象的引用 ,在能区别实例变量和局部变量时,this可省略,否则一定不能省略;
this() :
- 必须在构造器中使用,必须在第一行使用,this()和super() 互斥,不能同时存在;
- 调用本类的其他构造器,按照参数调用,也指代当前构造方法;
public class Demo{
int x;
int y;
public static void main(String[] args){
Demo demo = new Demo();
System.out.println(demo.x+"\t"+demo.y);
}
public Demo(){
this(1,1);//调用有参构造器;
}
public Demo(int x,int y){
this.x = x;//把传进来的参数赋值给对象的变量
this.y = y;
}
}
super. :
- 是访问父类对象,父类对象的引用,与this.用法一直;
super() :
- 一定在子类构造器中使用,必须在第一行使用,如果子类构造器内没有则是默认存在super();
- 调用父类的其他构造器,按照参数调用;
public Demo(){ int x = 10; int y = 20; public Demo(){} public Demo(int x,int y){ this.x = x; this.y = y; System.out.println(this.x+"\t"+this.y); } } class Demo1 extends Demo{ int x = 1; int y = 2; public Demo1(){ super();//调用父类的无参构造方法; super(x,y);//调用父类的有参构造方法; }; public static void main(String[] args){ System.out.println(suoer.x+"\t"+super.y);//打印出父类的属性值; Demo1 demo1 = new Demo1(); } }
重载和重写
重载:在同一个类中方法名相同,参数列表不同(参数个数、类型、顺序都不同),构造方法就是重载;
重写:对于存在继承关系的的情况下 ①方法名相同、②返回值类型一致、③参数列表一致; 子类重写方法,权限修饰符大于等于父类方法,子类抛出的异常小于父类抛出的异常;
package com.java.it;
public class Demo {
public void prints(String s){
System.out.println("方法一"+s);
}
//重载
public void prints(int i){
System.out.println("重写了方法一"+i);
}
public static void main(String[] args){
Demo demo = new Demo();
demo.prints("一");
demo.prints(1);
Demo demo1 = new Demo1();
demo1.prints("二");//测试父类的方法一已经被子类重写,所以打印的是"方法二二"
}
}
class Demo1 extends Demo{
//重写父类方法
public void prints(String s){
System.out.println("方法二"+s);
}
}
构造方法不能被重写,子类不能继承父类的构造方法;
继承的作用:使软件系统具有开放性,更好的进行抽象;(有点乱哈!)
继承的关键字:extends;
权限修饰符
修饰符 | 当前类 | 同包 | 子类 | 其他包 |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
public:公共权限,可以修饰类、成员变量、方法、构造方法;
protected:受保护权限,可以修饰成员变量、方法;
default:默认的权限,可以修饰类、成员变量、方法、构造方法(不用写关键字);
private:私有权限,可以修饰成员变量、方法、构造方法;