java基础篇--02<对类的操作>

来源:互联网 发布:小白编程网站 编辑:程序博客网 时间:2024/04/29 23:51

    普通类

  1. 在一个继承树体系中,要初始化一个类,会同时初始化该类的所有父类(注意:这里要区分类的初始化和实例化)

  2. 初始化可以理解为类的加载(第一次使用该类会被加载);实例化一般会伴随产生实例化对象

  3. java存储:

    1》桟:存储速度仅次于寄存器(较快),主要用来存储对象的引用和方法体中的局部变量,因为方法存在的时间很短,发在桟中有利于进行快速的存取运算;(这个的生存周期是在编译期间就已经确定的

    2》堆:桟中的引用所指向的对象就是存储在堆上,还有一些就是在这个对象里的类的成员变量,较桟的存取速度较慢;(他的管理是交给java的垃圾回收机制)

  4. java类中的this准则:在方法中谁调用就指向谁;在构造中指向类自己

  5. java中方法的不能独立存在,只能属于类或者类的对象;

  6. 执行方法”必须”用对象或者是类;

    有种形参可变的方法,例:

    1voidtest(inta,String ... books){};等价于

    2voidtest(inta,String [] books){};

            调用1》的话,可以这样

int a = 0;String s1 = "1";String s2 = "2";String s3 = "3";test(a,s1);test(a,s1,s2);test(a,s1,s2,s3);

so,等价于一个String数组


  1. 注意一个方法中最多只能有一个形参可变的;

  2. 方法重载:形参不同即可,但是不能拿返回值作为鉴别,因为在调用一个函数的时候,它的返回值是可以隐藏的;

  3. 下面的例子可以看出,父类的类变量在子类的每个实例中都有一个“副本”

class Father{int a = 5;}class Child extends Father{private String name = "child";Child(String name,int a){this.name = name;if(a!=0 ){super.a = a;}}void print(){System.out.println(name+" a = "+ a);}}public class Test{public static void main(String[] args) {Child c1 = new Child("c1", 0);c1.print();Child c2 = new Child("c2", 10);c2.print();Child c3 = new Child("c3", 0);c3.print();}}//result//c1 a = 5//c2 a = 10//c3 a = 5


  1. java中有个叫代码块的东西,使用{}框起来的代码,会在构造函数之前被调用,多个代码块按照排列顺序执行,都执行完了轮到构造函数;

  2. 这里添加一个,实例化一个类,他所调用的代码顺序                                                              
    public class Test{public static void main(String[] args) {Child c = new Child();}}class Father{public Father() {System.out.println("父类构造函数");}    {System.out.println("父类代码块");}        static {    System.out.println("父类静态代码块");    }}class Child extends Father{public Child() {System.out.println("子类构造函数");}    {System.out.println("子类代码块");}        static {    System.out.println("子类静态代码块");    }}结果=========父类静态代码块子类静态代码块父类代码块父类构造函数子类代码块子类构造函数

                                                                                                                                                                                                 
  3. 在第一次实例化一个类的时候,需要加载它的类

    class Name{                    static String action= "jump";                    private String age= "22";     }     Name name= new Name();

    1》加载类的时候会在堆上给类和类的静态变量(类变量)分配空间

    2》实例化对象,会在堆上给类的对象分配空间,对象中含有一些成员变量,但不包含类变量(因为它在加载的时候就完成了)

    312是在堆中的两个部分,1Name类存储的地方,它会有一个action的存储空间

    2name对象存储的地方,它有一个age存储的空间

    注意:这里的“22”,“jump”之类的字串在堆中又占着自己的一块地方,并不在12内,而12内中的actionage中存储的所谓的值,只是这两个字串的指向;

    图示如下:






  1. 局部变量(一种一般在方法里面定义的变量),在定义的时候并没有为其分配内存,直到初始化的时候jvm才会为其分配(且是分配在方法的桟内存中的);

  2. 堆中的资源若无指向,就会释放,因为是垃圾回收机制在管理;

    桟中的资源往往随方法或者代码块的执行完毕而结束,因为是JVM在管理(编译时期就已确定);

  3. 综上;可以通过少定义或使用类的成员变量,来加快程序的运行速度,更多的是使用局部变量;

    调用类的成员变量会要去到堆中抓取数据,慢!

  4. 理解封装:可以限制对“自己”的数据的不合理或者你不想看到访问;方法也是需要“封装”,即尽量通过参数传递来降低与其他方法的耦合,这样在处理大型的app就要好调整

  5. 讨论下修饰符:

    1private只能自己用

    2default自己,同包

    3protected自己,同包,不同包的子类

    4public公共(人如其名)

  6. 编写程序建议:

    分模块编写,尽量不允许其他模块直接访问本模块的数据,尽量少爆露方法给外部模块使用,尽量将功能实现细节“浓缩”在本模块内;综述,一切都是为了降低耦合

  7. 在构造器执行之前,其实系统就已经创建好了一个对象,并对其的成员变量进行了默认的初始化,只是当前不能被外部访问,只能在构造器中使用“this“进行访问,直到构造器执行完毕,会返回一个指向该对象的引用,至此,可以被外部访问

  8. 一个类可以有多个构造器,用于不同的场合,可能不同的构造器之间会有代码的重复,这就造成的在构造器中调用构造器的现象(节约代码);规则:B完全包含A,则调用A

  9. 注意”重写”和“重载”的区别,前者覆盖原有,后者多态(凭借参数不同);

    class In {public int a = 5;}public class Test extends In {public static void main(String[] args) throws IOException {Test tx = new Test();tx.print();}public Test() {super.a = 9;}void print() {System.out.println(super.a);}}


在子类中调用super可以去修改父类中的数据,因为其实父类的普通成员变量是“打包”在test对象实体一起的,即:每个test实例化对象有自己都有的super.a,test对象将他括在自己的存储里拉





class In {public int a = 5;public void eat() {// TODO Auto-generated method stubSystem.out.println("father eat");}}public class Test extends In{public int a = 1;public static void main(String[] args) throws IOException {              Test tx = new Test();              tx.eat();              In in = (In)tx;              System.out.println(tx.a);                                          in.eat();              System.out.println(in.a);}public void eat() {// TODO Auto-generated method stubSystem.out.println("child eat");}    void print(){    System.out.println(super.a);    }}


可以看见,Test继承In,重写Ineat(),

1》这时候new一个Test(子类对象),访问txeat()和a成员变量值为Test(子类自己的东西)

2》将tx(子类对象)强制转化成In(父类对象),再访问eat()和a成员变量值,eat()为tx(子类)的,

a的值却是In(父类)





  1. objStrinstanceof String强制类型转换之前检查objStr这个对象能否转化成String这个类型

  2. 包装类(Integer)可以拿来和数值直接进行比较,效果相当于直接取出包装类所包装的数值进行比较,而两个包装类比较,只有里面存的指向同一个对象才会相同。可以把数值直接赋值给包装类

  3. java特有的常量池,能保证相同的字符串直接量只有一个,不会产生多个副本;(对象池—针对包装类存在from-128 to 127才能使用对象池)

  4. final修饰的成员变量jvm不会对其进行隐式的赋值,需要程序员手动来进行初始化;

  5. 如果final修饰的变量编译时的值已确定,那么接下来在程序中使用到的地方都会被“宏替换”,这节约了运行的成本;




抽象类和接口

===============================

  1. 抽象类的抽象方法虽然可以通过普通类的空方法来实现,但是写成抽象类算是对读者的一种提醒;另外使用抽象类也可以很好的管理子类设计的随意性,因为子类必需实现父类提供的所用抽象方法;

  2. 接口中不可以定义static方法;

  3. 内部类可以用外部类private修饰的,但是外部类不能使用内部类的东西,因为,newwai()一个外部类调用外部类的方法,而这个方法调用的内部类的方法(这时候内部类还没有实例化,就会造成问题);


 class Out{ class In{public In(){}}}public class Test extends Out.In{     public Test(Out out){     out.super();     }}


1》要调用内部类的构造函数只能通过外部类的实例化

2》调用super()父类的构造器即内部类的构造器

0 0