Java基础知识整理一(JRE、JVM、基…

 

 

 

Java基础知识

1JDKJVMJRE

    高级计算机语言按程序的执行方式可以分为:编译型和解释型。Java语言比较特殊,需要经过编译步骤形成平台无关的字节码文件,也就是class文件,然会在由Java解释器来执行。负责解释字节码文件的就是Java虚拟机JVM,所有平台上的JVM向编译器提供相同的编程接口,二编译器只需要面向虚拟机,生成虚拟机能理解的代码。字节码文件是平台无关的,只面向JVM,不同平台的JVM是不同的,但是他们都提供了相同的接口,JVM是Java跨平台的关键部分。JDKJava标准开发包,他提供了编译、运行Java所需的各种工具和资源,包括Java编译器,Java运行时环境和常用的Java类库等。JRE,即Java运行时环境,是Java运行的必须条件,它包括JVM和和其他环境知识,如类加载器,字节码校验器等。二安装JDK时就会默认安装好JRE。安装好JDK后一般要配置环境变量,在PATH中加入环境变量,即设置JDK安装目录的bin所在的路径。然后就可以使用javacjava命令来编译和运行Java文件了。

    编译语法为:javac –d   字节码文件目标路径    源文件路径

    运行语法为: java   类路径及名称

2Java的垃圾回收机制

    Java程序的内存分配和回收都是JRE在后台自动进行的,JRE会负责回收不再使用的内存,这种机制被称为垃圾回收。Java的堆内存是一个运行时数据区,用来保存类的实例。当一个对象不再被引用的时候,即当没有对象引用指向原先分配给某个对象的内存时,该内存成为垃圾。垃圾回收包括回收不再使用的内存和整理内存碎片。

    优缺点:优点是很好的提高编程效率,减轻编程负担,保护了程序的完整性,是Java安全策略的一个重要部分。缺点是开销较大,影响程序的性能,Java虚拟机必须实时的跟踪程序中所有的对象,以确定那些是垃圾。

3、基本数据类型注意

    byte类型不能自动转换为char类型,int类型不能自动转换为String类型,所以以下都是错的:byte b=9char c=bString d=12

    特别注意,float a=12.7也是错的,因为默认是double类型的,以上都需要强制转换。

    还有一个状况,基本类型与String用加号连接后,将成为String类型。但要注意一点区别,如3+4+hello”结果为7hello,而“hello+3+4结果为hello34

4Java运算符的优先级比较

   

运算符说明(按优先级排列)

Java运算符

分隔符

[]  ()  {}  , ;

单目运算符

++  --  ~  !

强制类型转换运算符

(type)

乘法除法求余运算符

*  /  %

加减运算符

+  -

移位运算符

<<  >>  >>>

关系运算符

<  <=  >=  >  instanceof

等价运算符

==  !==

按位与

&

按位异或

^

按位或

|

条件与

&&

条件或

||

三目运算符

?:

赋值运算符

= += -= /= &= |= ^= %= <<= >>= >>>=

5breakcontinue结束循环体

    在循环体中,使用breakcontinue可以结束循环体。break用于结束当前所在的循环体,跳出循环执行循环体后面的语句,continue用于结束当前这次循环,执行下一次循环。另外,这些循环不仅能够结束其所在的循环,还可以通过添加标签结束外层循环,此时需要在break后紧跟一个标签,用于标识一个外层循环。如:

    public static void main(String[] a){

        outer:

            for(int j=0;j<10;j++){

                …;

                for(int i=0;i<10;i++){

                    if(…)

                    break outer;

               }

            }

        }

    此时,执行到符合if中的判断条件时,不仅会跳出内层循环,也会跳出外层循环。continue用法也是如此。但要注意的是,紧跟在break或者continue后的标签,英爱在break或者continue所在的循环外之前定义才有意义。

6Java的数组类型

    数组也是一种数据类型,它本身是一种引用类型。由于数组是一种引用类型的变量,因此当使用它定义一个变量时,仅仅表示定义了一个引用变量(也就是定义一个指针),这个引用变量还未指定任何有效的内存,因此定义数组时不能指定数组的长度。而且由于定义数组时仅仅定义了一个引用变量,并为指定任何有效的内存空间,所以还没有内存空间来存储数组元素,因此这个数组也不能使用,只有对其进行初始化之后,才可以使用。

    数组的初始化方式有两种,一种是静态方式初始化,即显式指定每个数组元素的初始值,如String []a=new String[]{“hello”,”world”};另一种是动态初始化,初始化时程序员只指定数组的长度,由系统为数组分配初始值。如:int price=new int[5];注意不要静态初始化和动态初始化一起使用,也就是说不要在进行数组初始化时,既指定数组的长度,也为每个数组分配初始值。

    JDK1.5提供了foreach循环来遍历数组元素,使用该循环时,foreach中的循环变量相当于一个临时变量,系统会把数组中的元素依次复制给这个临时变量,而这个临时变量并不是数组元素,它只是保存了数组元素中的值,因此这样是改变不了数组中的值的。

    内存中的数组:实际的数组元素是被存储在堆内存中的,数组引用变量是一个引用类型的变量,被存储在栈内存中。只有通过数组引用变量才能访问堆内存中的数组元素。只要类型兼容,可以让一个数组变量指向另一个实际的数组而不指向原来的数组,原来的数组可能会被当做垃圾被收回。

    值类型的数组初始化:数组元素的值直接存储在对应的数组元素中。初始化时,栈内开辟了一块内存存放数组引用变量的引用,堆内存中存入数组的值。

    引用类型数组的初始化:如一个自定义一个引用类型Person,执行Person students;时,仅在栈内存中开辟一块空间,存放引用变量,并未指向任何有效的内存。执行students=new Person[2]时,程序对数组执行动态初始化,动态初始化由系统为数组元素分配默认的初始值null;即堆内存中每个数组元素的值都是null。这时假如再定义一个Person类型的实例zhang,其年龄为20,身高为176;则类似的,栈内存中有一个引用变量zhang,指向堆内存中的实际对象,一个年龄为20身高为176的具体值。这时,再令studets[0]=zhang;则堆中的那个第一个数组元素同样存储了引用,即其值为zhang这个对象的引用,然后再指向在堆中的真正实例。其图如下:

 



7Java方法的参数传递机制

    Java里方法的参数传递方式只有一种,那就是值传递。所谓值传递,就是将实际参数值的副本传入到方法内,而参数本身不受到任何影响。对于基本类型的参数传递,实际参数是存储在栈内存中的值,传入到方法内部的也是在栈内存中的参数的一个副本,即也是存储在栈中的值,是参数的副本。对于引用类型,传递的是引用的值,即参数在堆内存中的地址值,所以当方法里对参数有改动时,堆中的数据也会随之改变,但是“值传递”的原则还是正确的。

8、方法的重载、重写(覆盖)

    方法重载是指在同一个类里定义多个同名方法,而形参列表不同。至于方法的其他部分,如返回值、修饰符等,与方法重载没有任何关系。方法重写一般是指子类重写父类中的方法,方法的重写要遵循“两同两小一大”原则,即方法名和参数列表要相同,子类方法返回值比父类更小或者相等,子类方法抛出的异常比父类抛出的异常更小或者相等,子类方法的修饰符比父类方法的修饰符范围更大或者相等。覆盖方法和被覆盖的方法要么都是实例方法要么都是类方法,不能一个是实例方法一个是类方法,否则编译时会报出语法错误。当方法覆盖成功后,子类对象将不能访问父类中被覆盖的方法,但子类对象可以在子类中通过super关键字来访问父类中被覆盖的方法。如果父类中的方法是private的,那么子类无法访问父类中的该方法,当然也就不存在重写覆盖,如果子类中也有一个与之同名的方法,那么他们是完全不同的两个方法,而没有任何联系。

9、关于构造方法

    当一个类中没有自定义构造器时,编译器会为该类添加一个默认的无参构造器,如果定义了构造器,则编译器不会再添加默认无参构造器。Java中子类不能继承父类的构造器。但是子类可以在自己的构造器中通过super关键字来显式调用父类的构造器,不过它必须出现在子类构造器中的第一行代码处。

    实例化一个类时构造器的执行顺序:

1、              子类构造器执行体的第一行使用super显式调用父类构造器,系统根据super调用里传入的实参列表调用父类对应的构造器。

2、              子类构造器执行体的第一行使用this显式调用本类中的重载的构造器,体统根据this调用类传入的实参列表调用本类的另一个构造器,执行本类的另一个构造器时将会调用父类构造器。

3、              子类构造器执行体中既没有super关键字也没有this关键字,系统将会在执行子类的构造器之前,隐式地调用父类无参构造器。

总之,在实例化子类的对象时,父类构造器总会子类构造器之前执行,不仅如此,执行父类构造器时,系统将会再次上溯执行其父类的构造器,一次类推。

注意:在创建对象时,对象所在类的所有数据会先进性初始化,完成初始化工作之后,才调用构造方法来创建对象。子类构造器在执行之前会先去执行父类构造器。一般父类中自定义了构造方法之后,应该再添加一个无参构造方法,以供子类构造方法显示或者隐式调用。如果父类中定义了带参数的构造方法而没有定义无参构造方法,系统此时不会给父类添加默认无参构造方法,这时在类初始化时或者子类构造器在执行时,将会找不到父类无参构造方法,这样会编译报错。解决办法有两个,一个是如前所说在父类中添加无参构造方法,另一个是在子类构造方法中用super关键字显示调用父类构造方法,这时子类构造器不会再去隐式调用父类的无参构造器。

10Java中的多态

    Java引用变量分为两种类型,一种是编译时的类型,一种是运行时的类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现多态。当把一个子类对象直接赋给父类引用变量时,则编译时类型是父类型而运行时类型是子类型。如SuperClass a=new SubClass();在实际运行时,通过该引用调用引用变量的方法时,其方法行为总是像子类方法的行为,也就是说,如果调用子类中重写的父类的方法,此时会执行子类中的方法。这里要注意,方法具有多态性,而属性不具有多态性。也就是说,如果父类和子类中都定义了同名属性,则通过父类行的引用调用的仍然是父类型中的属性。另外要注意,引用变量在编译阶段只能调用其编译时类型所具有的方法,也就是说,如果子类中有方法a()而父类中没有,编译时通过父类引用来调用a()方法时会报错。如果一定要调用,则需要进行强制转换,将父类型强制转换成子类型,这时便可以调用子类中独有的方法。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值