Java学习——静态成员,对象的应用、继承、抽象类、接口

静态成员

static 静态修饰符,修饰类中成员。被static修饰的成员称为静态成员(类成员),不用static修饰的成员称为实例成员。

1. 实例成员

实例成员属个别对象所有,彼此之间不能共享

2. 静态变量

静态变量是一个公共的存储单元,类的任何一个对象都可以访问到同一数值,类的任何一个对象去修改它时,也都是在对同一内存单元做操作
静态变量不需要实例化就可以使用,也可以用实例对象来访问静态变量
使用格式:类名.静态变量名; 对象名.静态变量名;
类中若含有静态变量,则其必须独立于方法之外

class Cylinder
{
    private static int num=0;
    private double radius;
    private int height;
    private static double pi=3.14;
    String color;
    public Cylinder(double r,int h,String str)
    {
        radius=r;
        height=h;
        color=str;
        num++;
    }
    public void show()
    {
        System.out.println("圆柱底半径:"+radius);
        System.out.println("高:"+height);
        System.out.println("颜色:"+color);
        System.out.println("创建了"+num+"个对象");
    }
    double area()
    {
        return pi*radius*radius;
    }
    double volume()
    {
        return area()*height;
    }
}
public class Test
{
    public static void main(String[] args)
    {
        Cylinder volu1=new Cylinder( 2.5,5,"红色");
        System.out.println("圆柱底面积="+volu1.area());
        System.out.println("圆柱体积="+volu1.volume());
        volu1.show();
        Cylinder volu2=new Cylinder( 1.0,2,"蓝色");
        System.out.println("圆柱底面积="+volu2.area());
        System.out.println("圆柱体积="+volu2.volume());
        volu2.show();
    }
}

3. 静态方法

静态方法实质是属于整个类的方法,被所有的对象共用,不能直接访问实例变量和实例方法
调用静态方法时,可以直接使用类名,也可以用某一个具体的对象名来调用
使用格式:类名.静态变量名(); 对象名.静态变量名();
通过对象名调用静态方法时必须先创建对象

class Cylinder
{
    private static int num=0;
    private double radius;
    private int height;
    private static double pi=3.14;
    String color;
    public Cylinder(double r,int h,String str)
    {
        radius=r;
        height=h;
        color=str;
        num++;
    }
    public static void show()
    {
        System.out.println("创建了"+num+"个对象");
    }
    double area()
    {
        return pi*radius*radius;
    }
    double volume()
    {
        return area()*height;
    }
}
public class Test
{
    public static void main(String[] args)
    {
        Cylinder.show();
        Cylinder volu1=new Cylinder( 2.5,5,"红色");
        System.out.println("圆柱底面积="+volu1.area());
        System.out.println("圆柱体积="+volu1.volume());
        volu1.show();
        Cylinder volu2=new Cylinder( 1.0,2,"蓝色");
        System.out.println("圆柱底面积="+volu2.area());
        System.out.println("圆柱体积="+volu2.volume());
        volu2.show();

    }
}


对象的应用

在某些场合可以像使用基本类型变量一样使用对象

1. 对象的赋值与比较

赋值

在使用对象时,一般先用new创建对象,再对其进行操作处理。但有时不用new创建新对象也可进行赋值。
例:创建圆柱体类Cylinder,并对该类创建的对象进行赋值运算

class Cylinder
{
    private double radius;
    private int height;
    private static double pi=3.14;
    public Cylinder(double r,int h)
    {
        radius=r;
        height=h;
    }
    public void setCylinder(double r,int h)
    {
        radius=r;
        height=h;
    }
    double area()
    {
        return pi*radius*radius;
    }
    double volume()
    {
        return area()*height;
    }
}
public class Test
{
    public static void main(String[] args)
    {
        Cylinder volu1,volu2;
        volu1=new Cylinder( 2.5,5);//创建对象volu1
        System.out.println("圆柱1底面积="+volu1.area());
        System.out.println("圆柱1体积="+volu1.volume());
        volu2=volu1;//将volu1赋值给volu2
        volu2.setCylinder( 1.0,2);//重新设置参数
        System.out.println("圆柱2底面积="+volu2.area());
        System.out.println("圆柱2体积="+volu2.volume());

    }
}


比较

对象被赋值后,这两个引用变量中所保存的地址相等 (当参数是基本数据类型时,是传值方法调用,当参数是引用变量时,是传址方法调用)
以下面例子说明对象的比较

class Cylinder
{
    private double radius;
    private int height;
    private static double pi=3.14;
    public Cylinder(double r,int h)
    {
        radius=r;
        height=h;
    }
    public void compare(Cylinder volu)
    {
       if (this==volu)
           System.out.println("这两个对象相等");
       else
           System.out.println("这两个对象不相等");
    }
    double area()
    {
        return pi*radius*radius;
    }
    double volume()
    {
        return area()*height;
    }
}
public class Test
{
    public static void main(String[] args)
    {
        Cylinder volu1=new Cylinder( 2.5,5);
        Cylinder volu2=new Cylinder( 2.5,5);//创建新对象
        Cylinder volu3=volu1;//赋值
        volu1.compare(volu2);
        volu1.compare(volu3);
    }
}


2. 引用变量作为方法的返回值

引用变量不但可作为参数进行传递,而且也可以作为方法的返回值
创建个人类Person,在该类中定义一个以对象作为返回值的方法compare()

class Person{      //创建个人类
    private String name;
    private int age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Person compare(Person p){   //定义以对象为返回值的方法,返回值类型为对象
        if (this.age>p.age)
           return this;//返回调用该方法的对象,该例中为per1
        else
            return p;//返回参数对象,该例中为per2
    }
}
public class Test1 {
    public static void main(String[] args) {
        Person per1=new Person("张三",22);
        Person per2=new Person("李四",21);
        Person per3;
        per3=per1.compare(per2);
        if (per3==per1)
            System.out.println("张三年龄大");
        else
            System.out.println("李四年龄大");
    }
}

3. 类类型的数组

用来存放对象的数组,步骤如下
(1)声明类类型的数组变量,并用new运算符分配内存空间给数组;
(2)用new创建新的对象,分配内存空间给它,并让数组指向它。

class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void show (){
        System.out.println("姓名:"+name+"  年龄:"+age);
    }
}
public class Test1 {
    public static void main(String[] args) {
       Person[] per=new Person[3];//声明类类型的数组并用new分配内存空间
       per[0]=new Person("张三",20);
       per[1]=new Person("李四",21);
       per[2]=new Person("王五",22);//用new创建新对象并分配给数组元素
       per[2].show();
       per[1].show();//用对象per[1]调用show方法
    }
}

4. 以对象数组为参数进行方法调用

由上述例子可知,数组可以存放对象。因此,也可将对象数组作为参数传进方法里。
以对象数组作为参数传进方法,并返回对象数组中最小的成员变量

class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public static int minAge (Person[] p){   //以对象数组作为参数传递给方法
        int min=Integer.MAX_VALUE;//将min的初值设为int型整数的最大值
        for (int i=0;i< p.length;i++){
            if (p[i].age<min)
                min=p[i].age;//将数组对象中成员变量age的最小值存入min
        }
        return min;//返回对象数组中最小的成员变量的值
    }
}
public class Test1 {
    public static void main(String[] args) {
       Person[] per=new Person[3];
       per[0]=new Person("张三",20);
       per[1]=new Person("李四",21);
       per[2]=new Person("王五",22);
        System.out.println("最小的年龄为:"+Person.minAge(per));
    }
}

类的继承

类的继承是使用已有的类为基础派生出新的类,是程序代码再利用的概念。

被继承的类称为父类或超类,由继承得到的类称为子类。一个父类可拥有多个子类,,一个类只能有一个直接父类。

父类实际上是所有子类的公共成员的集合,子类是父类的特殊化。

子类继承父类可访问的成员变量和成员方法,也可修改、重写、添加成员变量和成员方法

1. 子类的创建

Java语言中类的继承是通过extends关键字来实现的,格式如下:

class SubClass extends SuperClass
{
      ...   
}

上述语句把SubClass声明为类SuperClass的直接子类
如果没有extends关键字,则该类默认为java.lang.Object类得到的

子类的构建方法

class Person1    //Person类是java.long.Object类的子类
{
    private String name;
    private int age;
    public Person1()//Person类的无参构造方法
    {
        System.out.println("调用了个人类的构造方法Person()");
    }
    public void setNameAge(String name,int age)
    {
        this.name=name;
        this.age=age;
    }
    public void show(){
        System.out.println("姓名:"+name+"  年龄:"+age);
    }
}
class Student extends Person1   //定义Student类继承自Person类
{
    private String department;
    public Student()  //Student类无参构造方法
    {
        System.out.println("调用了学生类的构造方法Student()");
    }
    public void setDepartment(String dep){
        department=dep;
        System.out.println("我是"+department+"学生");
    }
}
public abstract class Test2 {
    public static void main(String[] args) {
        Student stu = new Student();//创建Student对象并调用构造方法
        stu.setNameAge("张三",12);//调用父类方法
        stu.show();
        stu.setDepartment("计算机系");//调用子类方法
    }
}

在Java语言的继承中,执行子类的构造方法之前会先调用父类的无参构造方法,目的是为了帮助继承自父类的成员做初始化操作

严格意义上说,父类的构造方法是不能被继承的,但不代表子类不能调用父类的构造方法

调用父类中特定的构造方法

通过super()语句实现 必须写在子类构造方法的第一行
格式为super(参数列表),super()可以重载
Java在执行子类的构造方法之前,如果没有super(),会先调用父类无参构造方法,所以父类只定义了有参构造方法,编译将发生错误,解决方法是在父类定义一个无参构造方法

class Person1    //Person类是java.long.Object类的子类
{
    private String name;
    private int age;
    public Person1()//Person类的无参构造方法
    {
        System.out.println("调用了个人类的无参构造方法Person()");
    }
    public Person1(String name,int age)
    {
        System.out.println("调用了个人类的有参构造方法");
        this.name=name;
        this.age=age;
    }
    public void show(){
        System.out.println("姓名:"+name+"  年龄:"+age);
    }
}
class Student extends Person1   //定义Student类继承自Person类
{
    private String department;
    public Student()  //Student类无参构造方法
    {
        System.out.println("调用了学生类的无参构造方法Student()");
    }
    public Student(String name,int age,String dep){
        super(name,age);//调用父类的有参构造方法
        department=dep;
        System.out.println("我是"+department+"学生");
        System.out.println("调用了学生类的有参构造方法");
    }
}
public abstract class Test2 {
    public static void main(String[] args) {
        Student stu1= new Student();//创建Student对象并调用无参构造方法
        Student stu2= new Student("张三",12,"计算机系");//创建对象并调用有参构造方法
        stu1.show();
        stu2.show();
    }
}

super() 从子类构造方法调用父类构造方法
this() 同一类内调用其他构造方法
两者都必须放在构造方法内的第一行,因此两者无法共存于同一个构造方法

2.在子类中访问父类成员

super不但可以访问父类构造方法,还可以访问父类的成员变量和成员方法,但不能访问在子类中添加的成员。应用格式如下
super.变量名;
super.方法名();
无法在子类中访问父类private成员,但可访问protected成员

class Person1    //Person类是java.long.Object类的子类
{
    protected String name;
    protected int age;
    public Person1()//Person类的无参构造方法
    {}
    public Person1(String name,int age)
    {
        this.name=name;
        this.age=age;
    }// 父类中有参构造方法在该例中无用
    public void show(){
        System.out.println("姓名:"+name+"  年龄:"+age);
    }
}
class Student extends Person1   //定义Student类继承自Person类
{
    private String department;
    int age=20;
    public Student(String xm,String dep){
        name=xm;//在子类中直接访问父类的protected成员
        department=dep;
        super.age=25;//利用super将父类age赋值
        System.out.println("子类中的age="+age);
        super.show();// super可去掉
        System.out.println("系别:"+department);
    }
}
public abstract class Test2 {
    public static void main(String[] args) {
        Student stu1= new Student("张三","信息系");
    }
}

protected在子类中可直接调用也可以用super调用

3.覆盖

覆盖的概念与方法的重载相似,重载指在同一类内定义多个名称相同但参数个数或类型不同的方法,而覆盖是指在子类中定义名称、参数个数与类型均与父类中完全相同的方法,用以重写父类中同名方法的功能。

覆盖父类的方法

子类中不能覆盖父类中声明为final或static的方法,覆盖是子类的方法头与父类中的方法头完全相同,此时不能继承

class Person1    //Person类是java.long.Object类的子类
{
    protected String name;
    protected int age;
    public Person1(String name,int age)
    {
        this.name=name;
        this.age=age;
    }
    protected void show(){
        System.out.println("姓名:"+name+"  年龄:"+age);
    }
}
class Student extends Person1   //定义Student类继承自Person类
{
    private String department;
    int age=20;
    public Student(String name,int age,String dep){
        super(name,age);
        department=dep;
    }
    protected void show(){
        System.out.println("系别:"+department);
    }
}
public class Test2 {
    public static void main(String[] args) {
        Student stu1= new Student("张三",22,"信息系");
        stu1.show();
    }
}

说明:在子类中覆盖父类的方法时,可以扩大父类中的方法权限,但不可以缩小分类方法的权限

用父类的对象访问子类的成员

将以上代码主类更改为:

public class Test2 {
    public static void main(String[] args) {
       Person1 per= new Student("张三",22,"信息系");//声明父类对象per指向子类对象
       per.show();//利用父类对象per调用show()方法
    }
}

注意:只有覆盖发生时,才可通过父类对象调用子类方法

不可被继承的成员与最终类

final修饰成员变量,说明该成员变量是最终变量,即常量,程序中其他部分都可以访问,但不能修改。final修饰成员方法,则该方法不能在被子类覆盖,为最终方法。final修饰类,则该类不能再被其他类所继承,即该类不可能有子类,被称为最终类
一个成员变量,若被static final两个修饰符所限定时,就是常量,只能在定义时赋值。定义一个成员变量,只用final不用static,则必须且只能赋值一次,不能默认。可以在定义变量时赋初值,也可在某一个构造方法中赋值

Object类

Object类是所有类的源。

equals()方法

使用“==”和equals()方法比较对象的异同

class A{
    int a=1;
}
public class Obj {
    public static void main(String[] args) {
        A obj1=new A();
        A obj2=new A();
        String s1,s2,s3="qwe",s4="qwe";
        s1=new String("qwe");
        s2=new String("qwe");
        System.out.println("s1.equals(s2)是"+(s1.equals(s2)));
        System.out.println("s1==s3是"+(s1==s3));
        System.out.println("s1.equals(s3)是"+(s1.equals(s3)));
        System.out.println("s3==s4是"+(s3==s4));
        System.out.println("obj1.equals(obj2)是"+(obj1.equals(obj2)));
        System.out.println("obj1==obj2是"+(obj1==obj2));
        System.out.println("obj1=obj2后obj1.equals(obj2)是"+(obj1.equals(obj2)));
    }
}

”==“比较两个对象在内存中的首地址,equals()方法比较两个字符串包含的内容是否相同

toString()方法

功能:将调用该方法的对象的内容转换成字符串,并返回其内容

getClass()方法

功能:返回运行时对象所属的类

抽象类

抽象类下边分管子类,不能创建对象,不能用new运算符创建实例对象的类,它作为父类被它的所有子类所共享

抽象类与抽象方法

抽象类是以abstract修饰的类,定义抽象类的语法格式如下:

abstract class 类名
{
    声明成员变量;
    返回值的数据类型 方法名(参数表)
    {
    }
    abstract返回值的数据类型 方法名(参数表);——抽象方法,在抽象方法里不能定义方法体
}

抽象类只需要声明,不需要实现。
抽象类的子类必须实现父类中所有的抽象方法,或者将自己也声明为抽象的,当一种方法声明为抽象方法时,意味着这种方法必须被子类的方法所覆盖。
abstract不能与private、static、final或native并列修饰同一个方法。

抽象类的应用

示例:定义一个形状抽象类Shape,以该抽象类为父类派生出圆形子类Circle和矩形子类Rectangle。

abstract class Shape{
    protected String name;
    public Shape(String name){
        this.name=name;
        System.out.print("名称"+name);
    }
    abstract public double getArea();
    abstract public double getLength();
}
class Circle extends Shape{
    private final double pi=3.14;
    private double radius;
    public Circle(String shapeName,double r)
    {
        super(shapeName);
        radius = r;
    }

    @Override
    public double getArea() {   //实现抽象类中方法
        return pi*radius*radius;
    }

    @Override
    public double getLength() {    //实现抽象类中方法
        return 2*pi*radius;
    }
}
class Ractangle extends Shape{
    private double width;
    private double height;
    public Ractangle(String shapeName,double width,double height){
        super(shapeName);
        this.width=width;
        this.height=height;
    }

    @Override
    public double getArea() {
        return width*height;
    }

    @Override
    public double getLength() {
        return 2*(width+height);
    }
}
public class A {
    public static void main(String[] args) {
        Shape rec=new Ractangle("长方形",6.5,10.3);
        System.out.print(";面积="+rec.getArea());
        System.out.println(";周长="+rec.getLength());
        Shape cir=new Circle("圆",10.2);
        System.out.print(";面积="+cir.getArea());
        System.out.println(";周长="+cir.getLength());
    }
}

接口

接口的数据成员都是静态的且必须初始化,即数据成员必须是静态常量;
接口中除了声明抽象方法外,还可以定义静态方法和默认方法,但不能定义一般方法。

接口的定义

语法格式如下:

[public] interface 接口名称 [extends 父接口名列表]
{
    [public] [static] [final]数据类型 常量名=常量;    //定义常量
    [public] [abstract]返回值的数据类型 方法名(参数表);   //定义抽象方法
    [public] static 返回值的数据类型 方法名(参数表)
    {
         方法体
    }     //定义静态方法
    [public] default 返回值的数据类型 方法名(参数表)
    {
         方法体
    }    //定义默认方法

接口中的抽象方法不能有方法的实现,即不能有方法体,而接口中的静态方法和默认方法都必须有方法的实现,即必须要定义方法体。

接口的实现与引用

接口与抽象类一样不能用new直接创建对象,所以必须利用接口的性质来创建一个新的类,然后用它来创建对象。
利用接口创建新类的过程称为接口的实现。类似于继承,语法格式如下:

class 类名称 implements 接口名表{
}

一个类要实现一个接口时,要注意以下问题。

  1. 如果实现某接口的类不是抽象类,则在类的定义部分必须实现指定接口的所有抽象方法
  2. 一个类在实现某接口的抽象方法时,必须使用完全相同的方法名,否则只是在定义一个新方法,而不是实现已有的抽象方法
  3. 类在实现方法时,必须显式地使用public修饰符,否则将被系统警告为缩小了接口中定义的方法的访问控制范围
interface Shape{
    static final double pi=3.14;
    abstract public double getArea();
    abstract public double getLength();//声明抽象方法
}
class Circle implements Shape{  //以接口来实现类
    double radius;
    public Circle(double r)
    {
        radius = r;
    }

    @Override
    public double getArea() {
        return pi*radius*radius;//实现接口中的方法
    }

    @Override
    public double getLength() {
        return 2*pi*radius;
    }
}
class Ractangle implements Shape{
    private double width;
    private double height;
    public Ractangle(double width,double height){
        this.width=width;
        this.height=height;
    }

    @Override
    public double getArea() {
        return width*height;
    }

    @Override
    public double getLength() {
        return 2*(width+height);
    }
}
public class A {
    public static void main(String[] args) {
        Shape rec = new Ractangle(6.5, 10.3);//声明父接口变量,指向子类对象
        System.out.print("矩形面积=" + rec.getArea());
        System.out.println(";周长=" + rec.getLength());
        Shape cir = new Circle(10.2);
        System.out.print("圆面积=" + cir.getArea());
        System.out.println(";周长=" + cir.getLength());
    }
}

接口的继承

与类的继承不同的是,一个接口可以有一个以上的父接口,它们之间用逗号分隔,形成父接口列表。新接口将继承所有父接口中的常量、抽象方法和默认方法,但不能继承父接口的静态方法,也不能被实现类所继承。如果类实现的接口继承自另外一个接口,那么该类必须实现在接口继承链中定义的所有方法。

interface Face1{
    static final double pi=3.14;
    abstract double area();
}
interface Face2{
    abstract void setColor(String c);
}
interface Face3 extends Face1,Face2{
    abstract void volume();
}
public class Cylinder implements Face3
{
    private double radius;
    private int height;
    protected String color;
    public Cylinder(double r,int h){
        radius=r;
        height=h;
    }
    public double area(){
        return pi*radius*radius;
    }
    public void setColor(String c){
        color=c;
        System.out.println("颜色:"+color);
    }

    public void volume(){
        System.out.println("圆柱体积:"+area()*height);
    }

    public static void main(String[] args) {
        Cylinder volu=new Cylinder(3.0,2);
        volu.volume();
        volu.setColor("红色");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值