java基础篇

一.java的优势:

1.简单性:

    (1)java相对于c语言来说取消了指针的概念,也不需要过多关注内存分配和垃圾回收机制问题,java中的垃圾回收器是自动调用的。

    (2)java中不支持多继承所以相对于c语言来讲结构更简单,c语言的多继承最后形成的类图类似与网状结构过于复杂,而java中的单继承类似于树状结构,条理清晰,看起来更直观。但是java的采用了可以实现多个接口的方式解决了扩展和通用的问题。

2.跨平台型:

    由于java虚拟机(简称jvm)的运行屏蔽了与具体平台的相关信息,使得java语言编译的程序只需生成在jvm上运行的目标代码(二进制字节码文件/.class文件)就可以在不同平台上无需任何修改的运行。

3.面向对象:

    java中的面向对象原理就是一切皆对象,将所有的可统计、可直视的数据看做一个对象,让系统更简单

 

4.面向对象的四大特性:

    (0)面向对象的优势:各司其职、弱耦合性、可重用性和可扩展性

            [1]在一个系统中,对象都是各司其职的,对象应该保持简单性

            [2]对象与对象间的关系应该尽量弱化保持弱耦合性

            [3]类应该是可以多次重复调取使用的所以应该保持可重用性和可扩展性

 

    (1).封装:

            java中对封装的概念是由类来实现的,类是对象共性的抽象。

           任何对象都要有一个明确的边界,将对象分为内部与外部,边界有一个隔绝保护的作用,使得内外变化互不干涉;

           封装主要突出边界的作用,同时要把握好封装的粒度;

            粒度过大会造成对象的运行过于复杂,粒度过小会导致类数量过多导致系统运行过于复杂。

            粒度:系统中一个对象所占空间的大小。

    (2)继承:一个类最多只能有一个直接父类,类之间会形成一个简单的树状结构;

            父类:基本类(Superclass)  子类:衍生类(SubClass)

            之前说类是对象共性的抽象,那么父类就是子类共性的抽象,结合面向对象的编程思想就是提高可重用性而对子类进行的共性抽取。

    (3)多态:子类的对象可以看做是父类的对象;子类的对象可以放入父类中引用;这就是运行时多态;

                将不同的子类对象同一看做父类对象,屏蔽了不同子类对象之间的差异;
                【1】对象类型不变:  一个对象从创建好开始,它的类型就绝对不会改变;
                【2】只能对引用 调用引用类型中声明的方法
                【3】运行时  根据对象实际类型找子类覆盖之后的方法
                        子类引用赋值给父类引用,可以直接赋值
                        父类引用赋值给子类引用,必须强制类型转换;

                        当使用强制类型转换时, 能保证编译通过,但不保证可以运行,可使用ininstanceof判断类型是否一致

                【4】多态的两种表现形式
                    1.父类引用指向子类对象  关注子类对象的类型---》关注父类引用调用哪个子类;
                    2.接口引用指向实现对象  不关注显现类对象的类型--》只关注实现类是否实现了接口中的方法

    (4)抽象:

            抽象类无法创建对象,只能声明引用;
            抽象类可以理解为是一个类的半成品;
            抽象类的子类不是抽象类也可以放在抽象类的引用中;
            抽象方法:只有声明没有实现,(连代码块都没有);
            抽象类中可以有构造方法;      抽象类中不一定有抽象方法;
            如果一个抽象类中有抽象方法,那么它的子类如果不想成为抽象类就必须将父类的抽象方法全实现;

            这种实现相当于继承中的覆盖。子类实现了父类没有实现的部分;

            而方法的实现放在子类中,这样能更好的体现出‘把共性放在父类中’的原则;

二。java虚拟机 jvm

    1.jvm为什么可以实现跨平台:

    (1)java代码不是直接运行在cpu上的,而是运行在jvm中。

 

    (2)jvm是先将源文件编译成class文件,在由jvm解释执行class文件(先编译后解释运行)

    2.jvm的内存结构:

        java内存模型的主要目标是定义程序中各个变量的访问规则,即,在jvm中将变量从内存中存储/取出这样的底层细节。
        此处所说的变量并不是java编程中所定义的变量,而是指包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,后者是线程私有的不会被共享。

        java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存(类似于处理器的高速缓存),线程的工作内存中保存了该线程使用到的变量到主内存副本的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存中来完成。这里的主内存、工作内存与java内存区域的堆、栈、方法区不是同一层此内存划分。

    3.jvm内存结构

   

    其中方法区和堆区是线程共享的;

    jvm栈、本地方法栈、程序计数器是线程私有的;

    4.jvm堆、栈

        堆空间:存储对象,对象创建时创建,由GC回收垃圾对象时销毁;

        栈空间:存局部变量,方法调用时创建,方法调用完毕销毁

    5.为什么堆空间共享,栈空间独立

        堆空间方便多线程间的数据交互,栈空间防止多线程间数据相互影响;

    6.jvm调优

        主要是通过命令更改堆栈的分配比例和内存回收的方式,打印程序运行日志然后手动配置参数

        详情可参考点击打开链接 

        在你点击之前请看完这句话:Xms为jvm初始化内存,不要被其中的错别字所误导;

三。ClassLoader 类加载

    网上的说法众说纷纭,过程步骤更是从三步到七步都有,但是我们真的能记得住那么多东西吗。在这里我简单总结了一下,如有错误请指正。

    类加载是指将class文件读入内存中并为之创建一个Class对象的过程,当程序主动要使用某个类而这个类并不存在与内存系统中时系统会触发类加载,类加载过程:   

        (1)加载目标类先递归的构造其所有父类并为其分配空间

        (2)加载静态成员并初始化默认值,包括静态成员变量和静态代码块

        (3)创建对象,加载其所有非静态成员并初始化默认值

        (4)执行构造器,生成对象。

四。继承之覆盖于重载

    1.覆盖:指子类用一个方法替换掉从父类继承的方法,没有继承不叫覆盖;

        子类用特殊的方法实现替换掉父类继承给它的一般方法实现;
        覆盖时,返回值类型、方法名、参数表相同,访问修饰符相同或更宽;

    2.重载:允许定义多个同名的方法,参数表不相同;

        参数表不同:1参数个数不同 2 参数类型不同 3 参数类型排列不同  形参名不同不算重载!!!!

        让一个对象的同类方法,由于参数表的不同造成的差异,对用户屏蔽;
        由编译器在程序编译的时候,根据实参的类型选择一个合适的方法调用;

        重载又称为编译时多态。

         Java 中调用函数并不需要强制赋值,所以返回值类型不同不算重载,会导致编译不通过。

五。抽象类与接口的区别

    【1】相同点:
        1.都不能创建对象;
        2.都能创建引用;

2.都能创建引用;
        3.在编译后都会生成一个.class文件;
    【2】不同点:
        1.抽象类中定义的属性没有要求
           接口中的属性必定是公开的静态常量
        2.抽象类中定义的方法没有要求
           接口中的而方法必定是公开的抽象方法,jdk1.8后接口中使用default修饰的方法可在接口类中实现
        3.抽象类中可以有构造方法

           接口中不能有构造方法

    【3】什么时候用接口什么时候用抽象类

                抽象类既然被叫做类那么它就是可以被继承的,那么基于java的特性来说所有继承它的子类都会得到继承类中可继承的常量和方法。那么抽象类就应该是作为一个共性抽取的父类,一些在我们很子类中要使用的工具对象、常量、方法都应该放在抽象类中,以达到通用、去除冗余代码的目的,需要注意的是当我们需要使用抽象类中的常量来为子类提供使用时,一定要加上final修饰符保证常量不被某一个子类所修改导致其余子类调用错误。

                由于接口中的方法都必定是公开的抽象方法,那么我们在实现接口时就一定要实现其中所有方法,那么接口应该当做一个封装的工具或者说是一个约束来使用,让用户忽略方法的实现,只需要知道方法的执行结果。而且接口中的方法都是抽象方法那么在使用时我们更应该注意的就是不要把接口当做基类使用,因为这样你在每个实现类中都要写一个实现方法,造成大量的代码冗余。

六。垃圾回收器GC机制

    当一个对象没有任何引用被使用时将会被判定为垃圾对象,在GC运行时这个对象将被销毁;

    当堆区的对象空间达到一定程度时GC就会运行收集并销毁这些垃圾对象,但是,一次回收不一定会消除当前所有的垃圾对象。通常我们会配置堆区的内存为当前物理内存的80%,对象的生存时间越长那么被回收的时间也将会越长如果GC运行一次的间隔时间超过5秒那么就应该相应的缩小一些堆区的内存来提高GC的运行频率了,因为垃圾对象过多的占用内存会导致系统运行效率的严重降低。

我们也可以手动的去调用GC去进行垃圾对象的回收,但是好多大牛级别的人物都不建议我们这么去做。

-------------------------------补充-----------------------------

昨天有人问我说,抽象类与接口的区别中说抽象类可以有构造方法,那么这个构造方法是干什么用的?
1.基于java语法的特点每个类都会有一个默认的无参构造方法接口除外。无参构造方法会默认的调用父类的无参构造方法,如果它没有继承别的类,那么java默认它将继承与Object默认调用Object的无参构造方法;
2.基于类加载机制来说加载完一个类的静态成员后就会加载非静态成员第一个调用的应就是无参构造方法,用于在jvm中加载类并构造类的对象。
3.如果你真的去调用无参构造方法的构造方法的话你会发现它在后面给你添加了一个代码块,代码块的作用我们都知道的,那么我认为它的构造方法就是让你在通过创建对象的过程中执行一些其他/额外的功能。
4.并且,这个代码块中不仅可以写业务逻辑也可以在其中写一些方法的声明和内部类;
但是我并没有看到有人去真的使用抽象类的构造方法区创建它的对象,一般我们都是基于java多态的特性把子类对象放在父类的引用中来完成我们所需要的业务逻辑。[code=java]

首先我先定义一个抽象类来用于测试,包含一个属性、一个无参构造方法、一个有参构造方法和属性的get、set方法:

 public abstract class Test {
    private String id;
    public Test(){
        super();
    }
    public Test(String id){
        super();
        this.id = id;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}

然后在另外一个类中写一个测试方法,在这个方法里我创建了上面Test类的对象并且在后面的代码块中添加了一个内部类,声明了一个方法b(),然后保存它,编译通过;

public void testNewObject(){
        Test t = new Test() {
            class TestClass{
                private String name;
                public void a(){
                    System.out.println("1");
                }
                String getName(){
                    return name;
                }
            }
            public void b(){
                System.out.println("2");
            }
        };
    }

 

[/code]

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值