您的位置:首页 > 编程语言 > Java开发

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

2016-01-22 14:18 423 查看
普通类

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

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

java存储:
1》桟:存储速度仅次于寄存器(较快),主要用来存储对象的引用和方法体中的局部变量,因为方法存在的时间很短,发在桟中有利于进行快速的存取运算;(这个的生存周期是在编译期间就已经确定的)
2》堆:桟中的引用所指向的对象就是存储在堆上,还有一些就是在这个对象里的类的成员变量,较桟的存取速度较慢;(他的管理是交给java的垃圾回收机制)

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

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

执行方法”必须”用对象或者是类;
有种形参可变的方法,例:
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数组

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

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

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

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


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

这里添加一个,实例化一个类,他所调用的代码顺序                                                              
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("子类静态代码块");
}
}

结果
=========
父类静态代码块
子类静态代码块
父类代码块
父类构造函数
子类代码块
子类构造函数


                                                                                                                                                                                             

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

class Name{

static String action= "jump";

private String age= "22";

}

Name name= new Name();


1》加载类的时候会在堆上给类和类的静态变量(类变量)分配空间
2》实例化对象,会在堆上给类的对象分配空间,对象中含有一些成员变量,但不包含类变量(因为它在加载的时候就完成了)
3》1和2是在堆中的两个部分,1是Name类存储的地方,它会有一个action的存储空间
2是name对象存储的地方,它有一个age存储的空间
注意:这里的“22”,“jump”之类的字串在堆中又占着自己的一块地方,并不在12内,而12内中的actionage中存储的所谓的值,只是这两个字串的指向;
图示如下:



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

堆中的资源若无指向,就会释放,因为是垃圾回收机制在管理;
桟中的资源往往随方法或者代码块的执行完毕而结束,因为是JVM在管理(编译时期就已确定);

综上;可以通过少定义或使用类的成员变量,来加快程序的运行速度,更多的是使用局部变量;
调用类的成员变量会要去到堆中抓取数据,慢!

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

讨论下修饰符:
1》private只能自己用
2》default自己,同包
3》protected自己,同包,不同包的子类
4》public公共(人如其名)

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

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

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

注意”重写”和“重载”的区别,前者覆盖原有,后者多态(凭借参数不同);
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 stub
System.out.println("father eat");
}
}

public class Test extends In{

public int a = 1;

public sta
e4b8
tic 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 stub
System.out.println("child eat");
}

void print(){
System.out.println(super.a);
}
}


可以看见,Test继承In,重写In的eat(),
1》这时候new一个Test(子类对象),访问tx的eat()和a成员变量值为Test(子类自己的东西)
2》将tx(子类对象)强制转化成In(父类对象),再访问eat()和a成员变量值,eat()为tx(子类)的,
a的值却是In(父类)的

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

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

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

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

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

抽象类和接口
===============================

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

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

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

class Out{

class In{
public In(){

}
}
}

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


1》要调用内部类的构造函数只能通过外部类的实例化
2》调用super()父类的构造器即内部类的构造器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java基础 java