继承
java可以使用extends关键字,可以让一个类和另一个类建立父子关系。
特点:子类可以继承父类的非私有成员(成员变量,成员方法)
子类的对象是由子类和父类共同创建的
使用:
定义了一个父类:
cpp
public class people {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定义的子类:
cpp
public class teacher extends people {
private String skill;
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
public void printname()
{
System.out.println(getName()+"的技能有"+getSkill());//可以直接访问父类的成员方法
}
}
使用:
cpp
public class test {
public static void main(String[] args) {
teacher t1=new teacher();
t1.setName("hh");
t1.setSkill("java");
t1.printname();//hh的技能有java
}
}
可以看出子类创建出的对象可以使用父类和子类的成员方法。
权限修饰符
概念:就是用来限制类中的成员能够被访问的范围
|-----------|------|-----------|-------------|---------|
| 修饰符 | 在本类中 | 同一个包下的其他类 | 任意包下的子类 | 任意包的任意类 |
| private | y | | | |
| 缺省 | y | y | | |
| protected | y | y | y | |
| public | y | y | y | y |
操作:
cpp
public class fu {
public void publicmethod()
{
System.out.println("public");
}
protected void protectedmethod()
{
System.out.println("protected");
}
private void privatemethod()
{
System.out.println("private");
}
void method()
{
System.out.println("缺省");
}
public void test()
{
publicmethod();
privatemethod();
protectedmethod();
method();
}
}
cpp
public class test {
public static void main(String[] args) {
fu f1=new fu();
f1.test();
/* public
private
protected
缺省*/
}
}
可以发现在本类中可以访问四种类型的权限修饰符
cpp
public class test {
public static void main(String[] args) {
fu f1=new fu();
f1.test();
/* public
private
protected
缺省*/
f1.method();
f1.publicmethod();
f1.protectedmethod();
}
}
也可以发现可以在同一个包下的其他类可以访问除了private的其余三种权限修饰符修饰的成员
cpp
public class zi extends fu{
public void test()
{
protectedmethod();
publicmethod();
}
}
在任意包下的子类可以访问protected和public修饰的成员。
cpp
import com.he.extern2.fu;
public class test {
public static void main(String[] args) {
/*teacher t1=new teacher();
t1.setName("hh");
t1.setSkill("java");
t1.printname();//hh的技能有java*/
fu f1=new fu();
f1.publicmethod();
}
}
在其他包的任意类下可以访问public修饰的成员
cpp
public class test {
public static void main(String[] args) {
/*teacher t1=new teacher();
t1.setName("hh");
t1.setSkill("java");
t1.printname();//hh的技能有java*/
fu f1=new fu();
f1.publicmethod();
zi z1=new zi();
//zi.protectedmethod();//'protectedmethod()' has protected access in 'com.he.extern2.fu'
}
}
可见只能在子类下才能访问protected修饰的成员,子类的对象不行
单继承:
java是单继承的,一个类只能继承一个直接父类,但是可以多层继承;
object类是java所有类的祖宗
方法重写:
当子类觉得父类的某个方法不好用,子类可以重新写一个方法名称,参数列表一样的方法,去覆盖父类的这个方法。
注意:重写后,方法的访问,java会遵循就近原则
例如:重写父类的print方法
cpp
public class zi extends fu{
@Override//提示方法重写,写错名字就报错
public void print()
{
System.out.println("777");
}
}
- 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限(public>protected>缺省)
- 重写的方法的返回值类型 ,必须与被重写方法的返回值类型一样,或者范围更小
- 私有方法,静态方法不能被重写
- 加 @Override
重写object类的toString()方法:
cpp
public class student {
private String name;
int age;
public student() {
}
public student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
object类的toString返回的是对象的地址
打印默认是调用了对象的toString方法
cpp
public class test {
public static void main(String[] args) {
student s1=new student("hh",18);
System.out.println(s1.toString());//com.he.extern4.student@2f4d3709
//object类的toString返回的是对象的地址
//打印默认是调用了对象的toString方法
System.out.println(s1);//com.he.extern4.student@2f4d3709
System.out.println(s1.getName());
}
}
重写toString()方法后:
student{name='hh', age=18}
student{name='hh', age=18}
子类访问其他成员的方法:就近原则
父类:
cpp
public class father {
String name="父类";
public void method()
{
System.out.println("父类--method");
}
}
子类:
cpp
public class son extends father{
String name="子类";
public void printname()
{
String name="局部";
System.out.println(name);//局部变量
System.out.println(this.name);//子类成员变量
System.out.println(super.name);//父类成员变量
}
@Override
public void method()
{
System.out.println("子类---method");
}
public void showmethod()
{
method();//子类本身成员方法
super.method();//父类成员方法
}
}
子类构造器的特点:
子类的全部构造器,都会先调用父类的构造器,再执行自己的构造器
默认调用父类的无参构造器
cpp
class fa{
private int age;
public fa()
{
System.out.println("父类无参构造器");
}
}
class so extends fa
{
private int age;
public so()
{
//super();//默认
System.out.println("子类无参构造器");
}
public so(int age)
{
//super();//默认
System.out.println("子类有参构造器");
}
}
public class test1 {
public static void main(String[] args) {
so s1 = new so();
so s2 = new so(3);
}
}
结果:
父类无参构造器 子类无参构造器 父类无参构造器 子类有参构造器
如果父类没有无参构造器怎么办
cpp
class fa{
private int age;
public fa(int age)
{
System.out.println("子类有参构造器");
}
}
class so extends fa
{
private int age;
public so()
{
//super();//默认
super(3);
System.out.println("子类无参构造器");
}
public so(int age)
{
//super();//默认
super(4);
System.out.println("子类有参构造器");
}
}
public class test1 {
public static void main(String[] args) {
so s1 = new so();
so s2 = new so(3);
}
}
解决方法:在子类自己写一个父类有参构造器
在子类中先调用父类构造器的好处:
父类:
cpp
public class father {
private String name;
private int age;
public father() {
}
public father(String name, int age) {
this.name = name;
this.age = 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;
}
}
子类:
由于name,age是父类的成员变量,不能使用this,所以用super(),调用父类的有参构造器
super(name,age);
cpp
public class son extends father{
private String skill;
public son() {
}
public son(String name,int age,String skill)
{
//由于name,age是父类的成员变量,不能使用this,所以用super(),调用父类的有参构造器
super(name,age);
this.skill=skill;
}
public son(String skill) {
this.skill = skill;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
测试:
cpp
public class test {
public static void main(String[] args) {
son s1=new son("nnn",18,"java");
System.out.println(s1.getName());
System.out.println(s1.getAge());
System.out.println(s1.getSkill());
}
}
this(...)可以调用兄弟构造器
注意:this(...)和super()都要写到第一行,所以不能同时写
cpp
public class test {
public static void main(String[] args) {
student s1=new student("hh",45);
//假如用户没有输入age,默认age18
student s2=new student("aa");
System.out.println(s2.getName());//aa
System.out.println(s2.getAge());//18
}
}
class student
{
private String name;
private int age;
public student() {
}
public student(String name)
{
this(name,18);//调用下面的有参兄弟构造器,自己把18传进去
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
总结:
super(...)为对象包含父类这部分的成员变量进行赋值
this(...)在构造器中调用本类的其他构造器