类定义
修饰符 class 类名{
定义属性
定义方法
}
具体可以参照下图,类创建并实例引用方法,如果光声明不初始化,声明的对象时null,初始化要通过new
在类方法中引用属性,直接使用名称(和Python不一样)
我们定义好类属性后,其属性就是固定的,并不能在外给实例添加新属性,否则会报错,这点和python不一样
我们实例一个类后,声明另一个实例初始化引用这个实例,那他们就共享一块内存区域
类方法前的private和public
public可以使你实例化类后,在main函数等访问成员变量和方法,而private只能你在类内部调用变量和方法,是内部调用
类构造方法
我们定义类如下图时,使用的是系统默认的构造方法,给类实例初始化
我们也可以自定义构造方法,让系统执行实例时引用自定义构造方法,方法名必须和类名一样,一般是public的(private外界new不了),可以有传参或不传,下图是不传参的,我们new一个Human类时,实例就有了age=18,height=170的属性。如果你在类定义时同时有构造函数上图的定义属性和下图构造函数定义的属性,那实例后属性参数都有
我们可以定义传参的构造,这样我们就可以根据new时传参实现定制的实例,注意如果定义了需要传参的构造方法,那你的new时参数必须按位置和类型传入,否则会报错。还有参数名和要赋值的属性名不能重复,否则实现不了给属性赋值,只是参数自己赋值给自己。构造方法不能有返回值,因为函数本身默认创建对象。
我们定义类的时候可以同时定义无参和有参的构造方法,new的时候就可以视情况选择
我们就是想让参数名有意义和属性名一样怎么办,我们就使用this参数(类似python的self,表示为实例对象),this只在类中使用,表示使用的是类的参数,使用this.a调用类的a属性,注意这个a属性要事先声明,否则会报错,还有注意Human类需要写在MyData类外部,否则会报错
类属性初始常常推荐使用private,需要输出修改的通过类方法输出修改,防止外部不小心修改了实例属性
GC垃圾回收机制
变量回收,成员变量和局部变量,局部变量是方法调用完毕销毁空间,堆中区域引用计数为0时清空
静态成员变量Static,
当定义了静态成员变量,属性就相当于python里的类属性而不是实例属性,一个改动会影响所有,如下图代码
运行结果可以看出没有定义static的属性是跟实例构造属性一样,但静态属性和最后一个修改的一致,静态变量存于不同于栈,堆的方法区(其中的静态区),创建实例时,他们的静态变量为共同的内存区域,每个修改都会导致另一个引用属性变化
静态方法,函数前有Static,静态方法只能使用静态变量,如下图,想调用show就会报错,因为引用的name,age都不是静态变量,静态方法也存储于静态区,我们使其访问name,age时,不知道要调用的是那个实例的name,age
我们要还是想访问其属性呢,我们可以给静态方法传入类实例p,我们知道是哪个实例p,就可以调用了,注意下图调用的静态方法在函数中调用直接使用类来调用函数,将实例作为参数
我们定义静态变量有什么好处呢,比如我们定义圆类,下图代码没有什么问题,但是我们如果建立足够多的圆实例,那么堆内存空间每个实例都要给pi分配位置,实际上我们使用的都是一个数字,这时定义static属性就比较有意义,所有的实例pi属性只占用一个空间
如下图修改加了static,创建多个实例pi就会只占用一个内存空间,我们还偷偷改了private,因为我们不想外部去修改pi
我们加载类后,静态方法和变量就已经加载,不需要通过实例对象,我们之前一直在使用的main方法其实就是静态方法,我们的main方法有参数String[] args,这个是干嘛用的呢,其实是我们用命令行接受参数的,输入字符串数组args(元素是按空格分割的),我们可以在程序里遍历args,得到插图16的效果
我们的main方法需要设置成public的,如果设为private,编译不会报错,但是运行会报错提示找不到main方法,设置私有使其不能被外部访问
我们有时候定义static方法,可以不用创建实例,直接通过类来引用,比如创建工具类,,我们都知道Arrays的fill方法可以给数组填充,我们自定义下,如果不是定义的静态变量,就需要创建一个实例去调用方法了,我们常常还在工具类里定义私有的构造方法private ArrayTool(){}这样如果是别人使用就会报错,就知道不能通过实例化去调用方法
图中for方法不能写成for(int i:arr){i=number}来设置,因为i被赋值number后就不和arr对应得元素一个指向
像我们常用的Arrays,Math都是工具类,可以去看文档好好学习下相关方法
GC JAVA垃圾回收机制
我们内存空间栈和堆是有限的,函数局部变量是占用的栈空间,类成员变量调用的是堆空间,局部变量是函数运行完销毁,指示此内存空间可以被其他变量使用,如果是引用变量,如果其引用计数为0时,就会被清空(虚拟机JVM做)
main函数
main函数注意public static void main(String[] args){}为标准写法,不能省略参数String[] args不然会报错
我们可以探究下args究竟是什么,程序如下
第一次运行和之前一样java MyProgram,没有任何输出,第二次后面加上了字符串,打印了a,b,c,d。这里和python里sys.args有相同效果用于命令行接受参数
文档生成
我们对类开头加上文档注释就是帮助生成文档的,复习下文档注释/** */
对编译好的java文件,我们命令行使用javadoc -d -api xxx.java即可在当前文件夹下生成api文件夹,里面存有我们文档注释生成的网页,一般index.html是首页,我们使用浏览器,记得修改浏览器编码gbk来查看,否则乱码(注意所有想生成的文档类必须是public的)
静态代码块
我们在主类模块的其他类可以使用static{}定义静态代码块,当类被实例化后就会被执行,而且只会被执行一次
类的继承
class A extends B{} 在已经创建B类的情况下,创建A类,继承了B的属性和方法,可以方法覆盖,继承的好处可以将大部分大交集重复定义类简化,各自继承基类,然后独立设定自身属性方法即可
如果父类构造方法属性设置的是private,那子类是不能够通过获得父类属性的构造方法的,需要父类get及set属性的方法,然后子类来调用
我们使用子类传参构造方法时,需要使用super(args),因为默认是按super()父类无参的构造方法来,且必须放在构造方法的第一行