首页 > 编程语言 >java学习笔记--类、函数重载、this、static、继承、重写、多态

java学习笔记--类、函数重载、this、static、继承、重写、多态

时间:2022-12-14 22:45:11浏览次数:59  
标签:aa java -- void 多态 class int static public

<5>类

1)类和对象

类是把一类事物的静态属性和动态操作组合在一起所得的概念,相当于模型,或者说一个设计图纸。

对象是类的一个个体,是根据类这个设计图纸造出来的实物,会产生和消亡。

用汽车来做个比喻,类就是设计图,对象就是一辆辆生产出来的车。

class Person

{

int age;//age是类的属性,也叫类数据成员,字段,域

void shout()//shout是方法,也叫类的成员函数

       {System.out.println(“oh!I am”+age)//shout方法可以直接访问同一个类中的age变量}

}

 

2)类的构造函数

class A

{

       private int i; private int j;

       public  A()//构造函数的要求:无返回值,名字和自己所属的类相同。

              {System.out.printf(“构造函数被调用了”)}

}

class Test

{

public static void main(String[] args)

       {

       A aa=new A();

        }

}

输出结果为:构造函数被调用了。由此可见,构造函数在构造对象的时候会被调用自动执行。

 

构造函数可以带参,比如public A(int a, int b)

                                          {i=a; j=b;}

创建对象变成A aa=new A(1,2)。则是在创建A对象的同时,给其属性i,j赋了值。

构造函数可以有多个,比如:public A(int a, int b)//第一个

                                                 {i=a; j=b;}

                                                public A();//第二个

       A aa=A(1,2);会使用第一个构造函数。A aa=A();会使用第二个构造函数。

类中默认会有一个无参的构造函数A()

       所以就算在类中不定义A()的构造函数,A aa=new A();也是对的。但是如果你定义了A(),

那java就不会生成这个默认的无参构造函数A()。

 

3)用个例子说明“按钮”思想

class Triangle

{ int a ;int b; int c;

 void set(int i, int j, int k)

       {a=i; b=j; c=k}

}

class test

{public static void main(string[] args)

                     {

Triangle t=new();

                     t.a=1; t.b=2; t.c=3;//第一种赋值方法

                     t.set(1,2,3);//第二种赋值方法     

                      }

}

那么第一种和第二种哪种方法好?第二种好

因为第二种方法,相当于对类Triangle的内部细节进行了封装操作,并不暴露给用户,只是给用户提供了一些简单的接口,就像这里的set一样。用户不需要知道a,b,c,用户只需要知道在set里面输入1,2,3就能达到自己想要的效果。如果我不给你提供set接口,用户就永远不能对类的内部细节abc进行操作,提高了安全性。

 

3)访问控制符

public,protect,default(默认),private。

在一个类的内部,所有的成员都可以相互访问,访问控制符是透明的,访问控制符是针对外部访问而言的。不可以通过外部访问方式访问类内部的private成员,其他都可。

外部访问的两种方式:通过类名访问类内部成员、通过类对象名访问类内部成员

 

4)函数的局部变量和类中的属性初始化

是否会自动初始化:

        局部变量编译器不会自动进行初始化,属性会被自动进行初始化。函数中的局部变量如果不进行初始化,编译会出错。类中的属性如果不进行初始化,编译不会出错。

属性的自动初始化规则:

        byte,short int,long int,int,float,double会被自动初始化为0

        char会被自动初始化为‘\u0000’,表示空

        boolean会被初始化为false

        All reference(引用) type,相当于c中的指针类型,会被初始化为NULL

注意一旦编程者为类定义了初始化方法,系统就不再提供默认的初始化方法了

<6>函数的重载

同名的函数通过不同形参做相同的事情,这就是函数的重载。形参个数,形参顺序,形参数据类型必须至少有一个不同。举个例子:

C语言中,要实现相加操作

        int add1(int a,int b);

        double add2(int a,double b);

        int add3(int a,int b,int c);

由于形参的不同,要构造的相加的函数名也不同

但是java中,只要是相加,都可以同名。

        int add(int a,int b);

        double add(int a,double b);

        int add(int a,int b,int c);

虽然形参不同,但是相加的函数名相同。在调用函数时,要使用哪个函数,根据你传入的实参个数,实参类型,实参顺序来决定,你调用的是哪一个add函数。

注意,如果函数只是函数的返回值不同,而形参均相同,则不构成函数的重载,编译会报错。

 

 

 

<7>this

1)一个对象只含有属性的空间,多个对象共用一份方法的拷贝

class A

{

       private int i;

       public  A(int j)

              {i=j; }

       public void show()

              {

              System.out.printf(“i=%d\n”,i)

              }

}

class Test

{

public static void main(String[] args)

       {

       A aa1=new A(10);

       A aa2=new A(20);

       aa1.show();

       aa1.show();

       }

}

aa1,aa2存在栈里,A(10),A(20)存在堆里。aa1指向A(10),aa2指向A(20)。show函数存放在代码区。虽然aa1,aa2在内存中分别有自己的静态属性,但是动态可执行方法show方法只有只有一个,那么如何知道,show方法是被aa1还是aa2调用的呢?

实际上上面show函数,按照c语言写是这样

public void show(A *this)

              {

              System.out.printf(“i=%d\n”,(*this).i);

              } 

aa1.show()→aa1.show(aa1)        aa2.show()→aa2.show(aa2)

也就是说,按照c语言的理解,在调用show函数的时候,会传入对象地址,以此来判定是哪个对象在调用show函数。使用show函数的时候,会根据对象地址,来获取对应的对象属性来进行输出。

按照java的理解,this就是一个隐含的指针,在非静态成员函数的形参列表中。当前时刻,哪个对象调用该函数,就会把调用该函数的对象的地址赋给this指针,这样,在函数内部可以通过this访问在调用该函数的对象的成员。

 

2)this使用实例:

class A

{

       public int i=99;

       public  A(int i)

              {

                System.out.printf(“i=%d\n”,i); //在该方法里新定义了i,那么i就是这个新定义的i

              }

       public void show()

              {

              System.out.printf(“i=%d\n”,i);// 在该方法里没有新定义i,那么i就是类A的属性i

               }

}

public class Test

{

public static void main(String[] args)

       {

       A aa1=new A(10);

       aa1.show();

        }

}

//输出结果为10,99

class A

{

       public int i=99;

       public A(int i)

              {

               this.i=i;//this代表当前时刻正在创建的对象

               System.out.printf(“i=%d\n”,i);

               }

       public void show()

              {

              System.out.printf(“i=%d\n”,this.i)//this代表正在调用show函数的对象

               }

}

class Test

{

public static void main(String[] args)

       {

       A aa1=new A(10);

       aa1.show();

       }

}

//输出结果为10,10

<8>static

1)static的几个性质

一个属性前如果增加了static,那么这个属性就不只是针对某一个对象,而是所有的这个类的对象公用这个属性。或者说,这个属性属于类,不属于某一个对象。示例:

class A

{

public static int a=10;

public void show()

       {

       System.out.printf(“i=%d\n”, a)

       }

}

class Test

       {

       public static void main(String[] args)

              {

              A aa1=new();

              A aa2=new();

              aa1.a=20;

              aa2.show();

              }

}

//输出结果为20

static属性属于类本身,没有对象,仍然可以直接通过类名的方式访问该类内部的static属性。示例:

class A

        {

        public static int a=10;

        }

class Test

       {

       public static void main(String[] args)

              {

              System.out.printf(“i=%d\n”, A.a)

               }

}

//输出结果为10

static属性和方法虽然属于类本身,但是类对象也是这个类,所以可以通过类对象名的方式访问。示例:

class A

{

public static int a=10;

public static void show()

       {

       System.out.printf(“你好!”);

        }

}

class Test

       {

       public static void main(String[] args)

              {

              A aa1=new();

              aa1.show();

              System.out.printf(“%d\n”,aa1.a);

              }

}

//输出结果为:你好!10

static只表明了该成员可以通过类名访问的潜在特征,这个特征能不能表现出来,还需要满足一个条件,这个成员是非private的。

class A

{

private static int a=10;//private的static成员不能通过类名访问

private static void show()

       {

       System.out.printf(“你好!”);

        }

}

class Test

       {

       public static void main(String[] args)

              {

              A.show();

              A.a=20;

              }

}

//报错

静态方法可以通过类名调用和对象名调用,非静态方法只能通过对象名调用。所以,有静态方法调用的权限不一定有非静态方法调用的权限(比如只有类,没有类对象),有非静态方法调用的权限,一定也会有静态方法调用的权限。以此可得,静态方法不能访问非静态成员,非静态方法可以访问静态成员。

换个方式理解:静态的是共有的,大家都有,调用时候知道是哪个。非静态的话,不同的对象有不同的,调用时候不知道调用的是哪个对象的非静态成员。

class A

{

public static void f()

       {

       g();//error!说明静态方法不可以访问非静态成员

       }

public void g()

       {

       f();//ok!说明非静态方法可以访问静态成员

        }

}

一个类的属性可以是个类对象,或者说一个事物可以包含另一个事物,比如汽车包含发动机

class A

{

public int i;

}

class B

{

public A aa=new A();

}

//aa是个对象,但是同时,也是B的属性

 

2)static的运用

统计造出了几个对象

class A

{

private int i;

public static int cnt=0;

public A()

       {

       ++cnt;

        }

public A(int i)

         {

          this.i=i;

          ++cnt;

          }

public static int getcnt()

              {

              return cnt;

               }

class Test

              {

              public static void main(String[] args)

              {

System.out.printf(“当前的A对象的个数是:%d\n”,A.getcnt());

A aa1=new A();

System.out.printf(“当前的A对象的个数是:%d\n”,A.getcnt());

A aa2=new A(2);

System.out.printf(“当前的A对象的个数是:%d\n”,A.getcnt());

}

}

//输出结果为:0,1,2

保证A类型只造出一个对象

class A

{

public int i=20;

private static A aa=new A(); //aa的静态不能省, get方法静态不能访问非静态成员

private A()//static不用于构造方法,因为构造方法一定属于类本身,不需再加限定

       {}

       public static A getA()//静态不能省,因为外部无法创造出类对象,只能通过类名访问getA来创造对象

              {

              return aa;

               }

}

class Test

{

              public static void main(String[] args)

              {

               A aa1=A.getA();

               A aa2=A.getA();

               aa1.i=99

               System.out.printf(“%d\n”,aa2.i);

                If(aa1==aa2)

                        System.out.printf(“aa1和aa2相等\n);

                else

                        System.out.printf(“aa1和aa2不相等\n);

                }

}

//构造方法是私有,在外部不能直接创建A对象,只能在内部方法提供一个getA接口来返回A对象aa,无论调用多少次getA,都是一个类对象。

为什么private static A aa=new A();不会形成新对象和新aa的反复形成?个人理解,不知道是对是错。因为aa是static类型的,处在共享数据区。因为它属于类,不需要依附于对象存在。所以在没有形成对象的时候,就已经执行了这句代码,创建出了aa。而创建aa的同时也需要创建一个对象A。创建对象A的时候,会生成对象的静态属性i。但是由于static aa是属于类的,对象创建的时候,并不会再次创建aa,只生成了对象的静态属性i。所以最终的结果是,生成了一个指针aa,和aa指向的对象A,对象A中只包含静态属性i。同时对象A可以调用static aa,所以称aa也为对象A的属性。

<9>继承

1) 什么是继承

一个新类从已有的类那里,获得其已有的属性和方法。新类也叫子类、派生类。

旧类也叫父类、基类。还有一个说法叫超类,是所有类的老祖宗。

 

2) 继承有什么用

代码重用,形成一种类的层次体系结构,为多态创造条件。举个例子:

class Human

{

public String name=”张三”;

public int age=22;

}

Class Student extends Human

{

public double score=66.6;

}

//此时,类Student既有name,age属性,又有score属性。

 

3)单继承和多继承

单继承是说一个类继承一个父类,多继承是说一个子类继承多个父类。Java只支持单继承。

 

4)同包继承权限问题

和访问控制符有关,public、protected成员可以被继承,private成员不能被继承。private成员实际物理上已经被继承了过来,但是逻辑上不允许访问。

 

5)super

类的构造方法不会被继承,如果想要调用父类的构造方法,可以使用super;

一个构造函数里只能有一个super,如果有super必须放在构造函数的第一个语句位置;

如果不定义super,则构造函数里默认有一个super(无参),如果此时父类没有无参的构造函数,就会出错;

super的形参列表要和父类的构造函数形参列表有一个相同

举个例子:

class A

{

public int i;

public int j;

public A(int i,int j)

       {

         this.i=i;

         this.j=j;

        };

publie A(int i)

       {

        this.i=i;

        };

}

class B extends A

{

public int k;

public B(int i,int j,int k;)

        {

         super(i,j);//ok!用super调用A的有参的构造函数,可以避免对继承来的i,j属性手动初始化

         super();//error,父类没有无参构造函数引用

          A(i,j)//error,因为构造方法没有继承

         this.k=k;

        }

}

 

6)子类访问父类成员的方式

子类的类对象名、子类内部直接访问继承来的,子类类名访问父类static

我个人不喜欢郝斌这个说法,我理解为继承来的就是自己的。所以不叫访问父类成员,应该叫访问从父类继承来的自己的成员。

 

<10>重写

对于父类中的方法体不满意,在子类中重新定义父类已有的方法;

重写方法必须和被重写方法的方法名称,参数列表和返回值类型相同;

重写方法的访问控制符比被重写方法的要更大

举个例子:

class A

{

public void f()//被重写方法

       {

       System.out.printf(“哈哈”);

         }

public void f(int i)

         {

         System.out.printf(“嘿嘿”);

          }

}

class B extends A

{

public void f()//重写方法

       {

       super.f();

       f(10);//调用继承来的f(int i)

       System.out.printf(“你好”);

        }

}

public class test

{

public static void main(String[] args)

              {

              B bb=new B();

              bb.f();

               }

}

//输出结果是:哈哈嘿嘿你好

<11>多态

1) 什么是多态

一个父类引用,既可以指向父类对象,也可以指向子类对象,可以根据当前指向对象的不同,来调用不同对象里面的方法和成员;

 

2)多态使用的注意事项

class A

{

public void f()

       {

       System.out.printf(“AAAA”);

        }

}

class B extends A

{

public void f()

       {

       System.out.printf(“BBBB”);

       }

public void g()

        {

         System.out.printf(“BBBB”);

         }

}

public class test

       {

  public static void main(String[] args)

              {

              A aa=new A();

              aa.f();

              B bb=new B();

              bb.f();

              //B cc=(B)aa;error

              aa=bb;//ok

              aa.f();

              //aa.g(),error

              B cc=(B)aa

              cc.g();

              //bb=aa,error

       }

}

//输出结果为AAAA,BBBB,BBBB。

同样是aa,f(),为什么输出结果不一样呢?因为aa可以根据它自己当前时刻指向的是A类对象还是A子类对象,而自动决定调用的是哪个对象的f方法。

为什么aa=bb是对的,bb=aa是错的呢?因为父类引用可以指向子类对象,但是子类引用不能指向父类对象。怎么理解呢?父类是动物,子类是狗。动物包括狗,但是狗不能概括动物。

为什么aa=bb之后,可以使用f(),不能使用g()呢?因为父类引用指向子类对象之后,只可以调用从父类继承来的成员,不能使用子类自己本身独有的成员。

什么时候可以使用子类本身独有的成员呢?为什么B cc=(B)aa强制转化之前aa.g()出错,B cc=(B)aa强制转化之后,cc.g()可以呢?郝斌的说法是把父类转化为子类之后,子类的特有方法就可以进行调用。我个人理解还是和强制转化没关系,能否使用子类特有的成员,和存储这个子类对象的引用类型相关。

为什么在aa=bb之前,B cc=(B)aa的强制转化出错,之后,B cc=(B)aa的强制转化允许呢?因为只有在父类引用指向子类对象的时候,才能把父类引用的内容转化为子类引用的内容。

 

3)多态实例:

class A

{

public void f()

       {

       System.out.printf(“AAAA”\n);

  }

}

class B extends A

{

public void f()

       {

       System.out.printf(“BBBB”\n);

  }

}

class C extends B

{

public void f()

       {

       System.out.printf(“CCCC”\n);

  }

}

public class Test

{

public void g(A aa)

       {

  aa.f();

  }

 

public static void main(String[] args)

  {

  A aa=new A();     

       B bb=new B();

       C cc=new C();

       g(aa);

  g(bb);

  g(cc);

  }

}  

//输出结果为AAAA,BBBB,CCCC。也就是说,我在g函数只创建了一个A引用,凭借它指向的不同,就使用了它的子类BC里的函数f()。

 

标签:aa,java,--,void,多态,class,int,static,public
From: https://www.cnblogs.com/fjcz/p/16983869.html

相关文章

  • 欧拉路径和欧拉回路
    一.引入哥尼斯堡七桥问题。河中有两座小岛,7座桥,问:一个步行者怎样才能不重复、不遗漏地一次走完七座桥,最后回到出发点。答案是怎么走都不能满足。二.定义:1.欧拉回路:经......
  • java循环语句
    循环格式(下图)for(inti=0;i<=5;i++){number+=i;}System.out.println(number);过程:while循环格式初始化语句;while(条件判断语句){循环体语句......
  • if语句和switch语句
    if语句if格式if(关系表达式){语句体}if(关系表达式){语句体1;}else{语句体2;}(关系表达式){语句体1;}elseif{语句体2;}...else{语句体n+1;}执行流程:先计算关系表......
  • java数据类型(基本数据类型)
    java语言的数据类型分为:基本数据类型,引用数据类型从内存角度来看:基础数据类型存储在自己的空间中,特点:赋值给其他变量,也是赋的真实的值引用数据类型数据值存储在其他......
  • java数组
    数组概念:是指一种容器,可以用来存储同种数据类型的多个值。建议容器的类型和存储的数据类型保持一致。数组定义:没区别数据类型 [] 数组名数据类型数组名[]......
  • 基于springboot休闲娱乐代理售票系统设计与实现的源码+文档
    摘要网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合,利用java技术建设休闲娱乐代理售票系统,实现休闲娱乐代理售票的信息化。则对于进......
  • jmeter更换背景颜色
    1、启动jmeter,找到options-Lookandfeel:2、选择要更换的主题后重启......
  • 瓴羊Quick BI 权限管理:商业智能工具的领头羊
    当前,很多企业想通过引进商业智能工具让内部数据分析效率与智能化水平提高,建立起一套有效的数据分析与运行管理体系。在选择BI工具时,运算速度和功能多样性是考虑最多的,其他几......
  • Java大神常用Linux命令整理一
    1.cd用来改变目录案例cd进入用户的主目录cd/etc绝对目录模式cd./home相对目录模式cdhome相对目录模式cd..返回上一级目录2.ls列表显示文件和......
  • 基于springboot疫情防控期间某村外出务工人员信息管理系统设计与实现的源码+文档
    摘 要网络的广泛应用给生活带来了十分的便利。所以把疫情防控期间某村外出务工人员信息管理与现在网络相结合,利用java技术建设疫情防控期间某村外出务工人员信息管理系统......