zoukankan      html  css  js  c++  java
  • Java基础

    JAVA基础

    java概述

    特点:

    1. 编译期检查异常

    2. 体系中立,生成平台无关字节码。并且及时编译将热点字节序列编译成机器码

    3. 可移植性强,字节码面向虚拟机,强类型定义明确,规范中没有“依赖具体实现”

    4. 程序=算法+数据结构,面向过程强调如何操作数据,面向对象强点如何组织数据


    java基本程序结构

    java源代码编译后空白会被忽略。

    基本类型:

    1. 整型:long(8字节)、int(4字节)、short(2字节)、byte(1字节)

    2. 浮点型:double(8字节)、float(1字节)

    3. Unicode字符类型:char(2字节)

    4. 布尔类型:boolean(1字节)

    boolean编译后是int类型占用4字节,对于32位机器高效存取。boolean数组在oracle中每个元素编译为byte类型 通过 位操作可以保证幂等性;同一个数字 异或 两次返回原值,可以用于简单加密;A^B=C则C^A=B并且C^B=A

    关键字

    strictfp:严格浮点计算,可能会产生溢出 大数运算:BigInteger(整数)、BigDecimal(浮点数)

    Java类中五大成员:

    属性、方法、构造器、代码块、内部类

    Java只有一维数组,多维数组是不规则的数组,每一行都可以有不同的长度

    final用来修饰基本类型和不可变类型

    值传递:方法接受参数的值拷贝;引用传递:方法接受参数的地址拷贝

    方法签名:函数名称+参数类型,如indexOf(int)

    C++中一个构造器不能调用另外的构造器


    类与对象

    类成员:

    属性、方法、构造器、代码块、内部类

    java中默认访问权限下是包访问权限,包访问权限只能同一包中的其他类访问,子包以及上层包均不能访问

    有返回值的方法称为 函数,没返回值的方法称为 过程,返回值是布尔类型的函数叫做 谓词

    对象之间的关系:

    • 依赖(use-a):一个对象的方法操作另一个对象,应该尽可能的降低对象之间的依赖(低耦合)

    • 聚合(has-a):一个对象的属性是包含另外的对象(聚合也被称为"关联")

    • 继承(is-a):对象间的继承和实现关系

    一个对象的引用变量,并没有包含一个对象,而只是一个指针。因此不要在方法中返回成员对象,而应该返回一个克隆对象

    java中每一个实例方法第一个参数都是隐式参数,也就是该对象,在方法中 this 关键字表示该对象。而类方法(static修饰)没有隐式参数

    java是引用传递,向方法中传递参数时如果是基础类型,则会将原值复制给实参变量。如果传递参数是引用类型,则会将原对象的地址复制一份传递给实参引用。因此无论怎样实参的中的值都是在原值的基础的上的一份拷贝,在方法中对其改变并不会对方法外的实际值产生影响。

    验证方法中传递对象是地址拷贝,可以通过在方法中交换交换引用地址与方法外的对象进行比较。最终可以验证是同一地址的两份拷贝。

    finalize 在垃圾回收器清除对象之前调用,但是不知道具体调用时机

    import 只能用 * 导入一个包,import 编译器可以查看其它文件内部,去其他类寻找对象,所以和C++中的#include不同,C++不能查看其它文件内部,#include只是将外部声明特性加载进来

    继承

    子类能继承父类的 属性方法 但是不能访问父类private修饰的成员,同名属性子类会隐藏父类(不会重写),访问属性时通过 编译期 的变量类型来决定访问 父类 还是 子类的属性。而访问方法时,是通过 运行期 实际类型来决定访问方法

    java中所有继承都是公有继承,C++中::限定符在Java中通过super实现

    函数返回值不是 方法签名 的一部分,因此方法重载不可以用函数返回值作为区分

    如果一些父类方法没有在子类中被覆盖,则编译器会进行优化,可能会进行内联化(inline),通过final修饰的方法/类 一定不会在子类中实现,因此更有可能利用到 即时编译器的内联化优化

    向上向下转型是对应 继承链 来说,向上:子类->父类;向下:父类->子类;在C++中向下转型(强转)失败会返回空指针,转换后判断指针是否为NULL再使用,而java需要在转换前通过instanceOf判断能否转换

    子类实例 instanceOf 父类判断实例是否是该类的实例,即使实例是null,不会报错;会返回false;

    java中通过abstract声明抽象类/抽象方法,而C++中没有专门声明抽象类的关键字,约定在C++中只要包含一个或者多个纯虚函数则该类就为抽象类;抽象类则不能实例化实例,声明纯虚函数virtual 返回值类型 方法名(形参列表)=0

    C++中没有所有类的根类,java中Object是所有类的父类

    泛型不能是基本类型,java中的泛型式假泛型,JVM并不支持泛型,只是编译阶段通过checkcase检查类型

    Java类库中原设计将接口类的静态放发放在伴生类中(伴生类在原类名后加s,类中全是静态方法静态常量),jdk8以后接口可以提供默认实现,增加默认实现的目的是扩展父类的同时不会对子类造成影响

    重写规则

    1. 子类重写方法访问权限一定不能小于父类访问权限

    2. 子类参数列表必须与父类相同

    3. 子类方法的返回值类型只能和父类相同或者是父类返回值的子类

    4. 子类方法的抛出异常只能是父类抛出异常的子类或者相同类

    5. final 方法不能重写

    6. private方法会被继承但是对子类不可见

    7. 构造器隐式被static修饰

    8. 静态方法不会被重写,如果重写了则父类的静态方法会被子类静态方法隐藏,静态方法不具备多态特性,属于静态绑定,由调用的对象类型决定

    类加载过程:加载->验证->准备->解析->初始化

    static方法和属性在初始化之前在方法区被加载,而非static成员在初始化之后内动态创建

    常用接口

    需要实现克隆方法的对象都要继承Cloneable接口,并且重写clone方法,调用Object的clone(super.clone())并强制类型转换成子类会进行浅拷贝,需要手动再将引用对象深拷贝

    lambda表达式

    带参数变量的表达式叫做lambda表达式,源自《数学原理》中用lambda表示自由变量

    只有一个抽象方法的接口叫 函数接口,函数通过@FunctionalInterface修饰,大量的函数接口被定义在java.util.function,lambda表达式就是 函数接口 的匿名内部类实现。传入lambda表达式的参数必须是不变的,lambda表达式中的this是只创建这个lambda表达式的方法的this;传递参数的时候是通过匿名内部类的方式传递的,作用是 延迟执行代码,lambda引用的外部参数必须是 final 防止多线程下的变量不安全 lambda表达式中的this指向的创建lambda表达式的类对象 方法引用函数接口 的实现体有且只有一行方法调用代码,则可进行的简写形式

    // 函数接口定义
    @FunctionalInterface
    interface <函数接口名>{
      <函数返回值> <函数名称>([参数列表]);
    }
    // lambda 创建
    // 1.参数如果只有一个则括号可以省略
    // 2.参数类型可以推到则也可以省略
    // 3.如果实现只有一行代码则大括号也可省略
    <函数接口类> <函数接口对象名> = (参数列表)->{接口函数实现}

    <类名>::<类方法名>;
    <实例名>::<实例方法名>;
    // 传入接口方法的第一个参数会作为方法调用者,例如:String::compareToIgnoreCase 等同于(x,y)-> x.compareToIgnoreCase(y)
    <类名>::<实例方法名>;

    多态

    java中默认是动态绑定,父类引用指向子类对象方法调用的是子类实现,而C++中默认是静态绑定调用的是父类方法,如果使用动态绑定需要声明函数是虚函数或者纯虚函数

    内部类

    内部类模仿包访问权限;编译器编译后 外部类$内部类,内部类是一种编译器行为,虚拟机无感知;内部类编译后会加上final 外部类名 this$0引用外部类,可以访问外部类私有数据;包含内部类的外部类编译后会对每个属性(非final修饰)生成static 外部类属性类型 access$数字(外部类)的静态方法,在内部类访问外部类属性时会被调用;所以使用内部类不安全,可以构造虚拟机指令访问到私有方法;普通内部类不能包含静态属性和静态方法

    局部内部类

    java中使用可以使用局部内部类来实现 闭包,局部内部类被定义在某一方法内,局部内部类不仅可以访问到外部类成员(属性和方法),还可以访问到定义访问内的局部变量,但是访问的局部变量必须是final的;在编译过后访问的局部变量会将值复制作为局部内部类的属性值(final 类型名 val$局部变量名

    将外部变量声明为final是保证复制阶段局部变量和局部内部类拷贝一致,外部变量也可以叫做 自由变量 ,如果需要对局部内部类的外部变量做修改,则以将外部变量放在一个用final修饰的可变对象中,传入局部内部类

    匿名内部类

    局部内部类的一种,定义后即生成对象;没有构造函数,定义过程会调用父类构造器(匿名内部类必须作为一个父类的实现类);

    可以直接扩展一个类定义重定义代码块,做一些自定义操作。例:new ArrayList<int>(){{add(1);add(2)}},外面的大括号代表是作为匿名内部类实现,内部的大括号代表的是实现代码块(对象成员) 在静态方法中获取外部类名,可以通过new Object(){}.getClass().getEnclosingClass()获取生成当前Object对象的外部类

    静态内部类

    静态内部类又叫 内嵌类,不保存外部类的对象实例,可以定义静态和非静态成员

    最佳实践

    1. 实现compare方法如果是int类型最好不要要两个参数相减,如果是负数可能会产生溢出

    2. 通过steam可以创建指定类型数组,Person[] people = stream.toArray(Person[]::new):

    反射

    java运行期间为每个 对象 保存了所属 的信息

    对象的.getClass(); 类名.class Class.forName("类名");

    java中数组对象不支持向下转型,编写通用的数组方法,new创建Object[]数组,不能转换成实子类型,运行报错;通过 Array.newInstance(class对象,长度) 创建指定类型的数组对象(返回Object[]数据)可以向下转型成class类型对象

    自省(Intro Spector)

    java中自省机制是对Bean对象的属性一种通用调用方法,可以通过属性名获取对象的setter/getter方法;再通过反射调用;自省机制主要涉及三个类:InteroSpector、BeanInfo、PropertyDescriptor

    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    // 获取JavaBean描述
    BeanInfo user = Introspector.getBeanInfo(User.class);
    // 获取属性描述器
    PropertyDescriptor pd = new PropertyDescriptor(name, bean.getClass());
    // 获取Bean中所有属性描述符
    PropertyDescriptor[] pds = user.getPropertyDescriptors();
    // 通过属性描述符调用setter方法
    Method method = pd.getReadMethod();
    // 通过属性描述符调用setter方法
    Method method = pd.getWriterMethod();
    // 通过反射调用制定方法,返货/设置值
    Object result = method.invoke(user);

    异常

    其中Error和RuntimeException异常也称为 非受查异常,这种异常不受控(Error)或者应该避免发生(RuntimeException),因此开发者不要字定义此类的子类;其他异常被称为 受查异常

    java中只能抛出Throwable的子类,但是C++中可以抛出任何类型的对象,Java中捕获的异常默认以final修饰,代码中抛出异常会中止剩余代码执行,并且退出这个方法执行 java7自动关闭资源机制,关闭资源出现的异常被自动捕获并被抑制,并调用addSuppressed方法添加到被抑制的异常列表 异常“早抛出,晚捕获”

    // 耦合try-catch和try-finallys是最佳实践,因为这种设计方式不仅简单,而且能处理finally中可能出现的异常
    try{
       try{
    // 可能出现的异常
      }finally{
           // 关闭资源
      }
    }catch(受检查的异常类型 e){
       // 异常处理
    }

    断言机制

    断言机制使开发测试阶段插入的一些检查代码(如果检查不通过会抛出 AssertionError 异常)在发布时会自动移走,默认运行程序时是关闭断言的,通过运行程序加上-ea命令启用断言,启用和禁用断言是类加载器功能,不会降低程序运行速度;当禁用断言时,程序会跳过断言代码

    断言可以针对某个特定类或者特定包,通过-da参数来禁用断言使断言代码失效,有些 系统类 不是由类加载器创建而是直接由虚拟机直接加载,这些类通过-esa来开启断言 断言只用于开发和测试阶段,用于报告致命的、不可恢复的错误,是一种战术性工具,而日志是一种在程序整个生命周期都可使用的策略性工具

  • 相关阅读:
    FocusBI:MDX检索多维模型
    FocusBI:地产分析&雪花模型
    FocusBI:租房分析&星型模型
    FocusBI:《DW/BI项目管理》之SSIS执行情况
    FocusBI:租房分析可视化(PowerBI网址体验)
    Eclipse创建自定义HTML5,JSP模板
    小测试解析
    vue---组件通讯
    前期准备-Git篇
    npm install 关于 sass 屡次失败问题
  • 原文地址:https://www.cnblogs.com/leon618/p/13783399.html
Copyright © 2011-2022 走看看