java基础知识

面向对象的思想本质:以类的方式组织代码,以对象的方式组织数据。

JDK:java开发工具包,开发者用;

JRE:运行时环境,运行Java程序只需jre就够了;

JVM:java虚拟机。

三者关系:JDK 包含 JRE 包含 JVM。

IDE:集成开发环境。

一个源文件可以对应多个class文件;

一个源文件中可以有多个class,每个class编译时会对应生成一个class文件,该源文件中public修饰的class名必须和文件名一样。

Java语言释型还是编译型?还是两者都是?

      编译型语言:在程序运行之前,通过编译,将源程序翻译成机器语言,此后执行该程序就不用再进行翻译了。

      解释型语言:每次程序运行的时候,边运行边翻译。

Java的运行过程:Java源文件(.java)通过Java编译器(javac)编译生成一个ByteCode字节码文件(*.class),字节码由Java自己设计的一个

计算机(即Java虚拟机,JVM)解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定的机器上的目标机器码,然后在特定的机器上运行。Java的解释器的优点是比较容易让用户实现自己跨平台的代码,同一套代码可以在几乎所有的操作系统上执行。

      虽然Java的第一道工序是javac编译,但其目标文件是ByteCode,而并非机器语言,但后续可能有三种处理方式:

1、运行时,ByteCode由JVM逐条送给解释器,解释器将翻译成机器码运行。

2、运行时,部分ByteCode可能由实时编译器(Just In Time Compiler,JIT)编译为目标机器码再执行(以method为翻译单位,还会保存起来,第二次执行就不用再翻译为机器码了),因为考虑到有些JVM是采用纯JIT编译方式实现的,其内部没有解释器,例如:JRockit、Maxine VM。

3、RTSJ,继javac之后执行AOT二次编译,生成静态的目标平台码。

有的时候,可能是以上三种方式同时在使用,至少,1和2是同时使用的,3则需要程序员手工指定。

      我认为java是编译与解释两者之间的混合式语言。

很多资料说,C/C++等是编译型语言,而Java、C#、Python、JavaScript都是解释型语言,是通过解释器来实现的,其实这么说很容易引起误解:语言一般只会定义其抽象语义,而不会强制性要求采用某种实现方式,例如说C一般被认为是编译型语言,但C的解释器也是存在的,例如Ch……所以一般被称为“解释型语言”的是主流实现方式为解释器的语言,但并不是说它就无法编译。

编译时注释跳过,字节码文件中没有注释。

标识符不能以数字开头;标识符不能包含除了字母、数字、下划线、$之外的其他字符。

Java内部采用Unicode字符集,能识别汉字。

字符集问题:

1.ISO8859-1:西欧字符集,1个字节;

2.GB2312:大陆使用最早、最广的简体中文字符集;

3.GBK:上者的扩展,可以表示繁体中文;

4.GB18030:上者的扩展,可以表示名族语言;

5.Unicode(UTF-8):国际通用字符集,2个字节;

byte:1字节;-128 ~ 127

short:2字节;-2的15次幂 ~ 2的15次幂-1(-32768~32767)

int:4字节;-2的31次幂 ~ 2的31次幂-1(正负21亿,不用记)

long:8字节;-2的63次幂 ~ 2的63次幂-1(不用记),定义long类型变量时后面加“L”;

    在Java中有两个类BigInteger和BigDecimal分别表示大整数类和大浮点数类,理论上能够表示无线大的数,只要计算机内存足够大;

这两个类都在java.math.*包中;

float:4字节;浮点数有舍入误差。定义float类型变量时后面加“F”;

double:8字节;浮点数有舍入误差;

char:4字节

科学记数法:“e”表示10的次幂;3.14e5 = 3.14*10的5次幂 = 314000

Java中八进制数以“0”开头;十六进制数以“0x”开头;

二进制:Binary

八进制:Octal

十六进制:Hex

运算符详解:

      关于取余运算“%”:小数也可以进行取余运算。

      关于移位运算符:

           <<:左移运算:左移一次相当于乘以一个2;

           >>:右移运算:右移一次相当于除以一个2;

           如:

           12<<2=48;12>>2=3;

math类:Math.random()——产生随机数方法(随机产生的是一个小于1的小数);

int e = (int)(Math.random() * 5);//随机产生一个0-5之间的数;

switch语句注意:

      1:每一个case要加上一个break。

      2:JDK7新特性:switch(a)中a可以是字符串。

每行输出定量个数后换行:

乘法口诀:System.out.peintln(i+"*"+m+"="+(i*m)+" ");

API相关:

      API:应用程序编程接口;

      通过javaDOC生成api文档;

      生成API文档专用注释防范:/**

接收键盘输入类:Scanner

自动类型转换:容量小的数据类型可以自动转换为容量大的数据类型。

特例:int类型数只要范围不超过范围比之小的byte、short、char,都可以直接转换。

所有二元运算(+-*/···)都有类型提升的问题。

对象属性默认值:

      八种数据类型以外的任何默认值都为null;

      数字默认0;

      bool默认false;

      小数默认0.0;

内存分析

      栈:

          1. 每个线程私有,不能实现线程间的共享;

          2. 局部变量放置于栈中;

          3. 栈是由系统自动分配,速度快;

            4. 栈是一个连续的内存空间;

      堆(包含方法区):

          1. 放置new出来的对象;

          2. 堆是一个不连续的内存空间,分配灵活,速度慢;

      方法区(也是堆):

          1. 被所有线程共享;

          2. 用来存放程序中永远是不变或唯一的内容。(类的代码信息、static静态变量、字符串常量)

虚拟机内存管理垃圾回收机制:

      程序员无权调用垃圾回收器;

      程序员可以通过system.gc()通知GC运行,但是并不能保证立刻运行;

      finalize方法,是java提供给程序员用来释放对象或资源的方法,很少用。

static详解

      static变量从属于类————存放在内存中的方法区,而new出来的对象发在堆区,从属于对象。

      所以在普通方法中可以调用静态方法和属性,反之在静态static方法中不能调用非静态的属性和方法。

this、super关键字详解:都是隐式参数。

      普通方法中:this总是指向调用该方法的对象;

      构造方法中:this总是指向正要初始化的对象;

      注意:this不能用于static方法。因为静态方法不能调用非静态的方法和属性;

      特殊用法:this(参数);//在一个构造方法中调用另一个构造方法,但是必须在当前构造方法的第一行;

final关键字详解:Cannot override the final method

      修饰的变量不能再次被赋值;其修饰的方法不能被重写,但可以被重载;

      其修饰的类不能被继承(类中包括若干方法);

 

内部类详解

      适用场景:只考虑为其外部类提供服务;

      每个内部类能独立实现接口或继承类;

      成员内部类:可以无条件访问外部类的所有成员属性和成员方法(包括private)。当成员内部类的field或method与外部类相同时默认访问的是内部类的。每个实例都包含一个指向外围实例的引用,若需要访问外围实例可使用:外部类名.this.field/method。在外部类中访问内部类的成员时需要先创建一个外部类,使用 .new语法。

Outter outter = new Outter();

Outter.Inner inner = new outter.new Inner();//必须通过Outter对象来创建

局部内部类:定义在一个方法内部或者是一段作用域内的类,仅限于在作用域内访问;

静态内部类:不依赖于外部类,不能用外部类的非static的域或者方法;

      非静态内部类必须寄存在一个外部类对象里,非静态内部类对象单独属于外部类的某个对象;

      非静态内部类可以使用外部类的成员,但是外部类不能访问非静态内部类的成员;

  1. 为什么成员内部类可以无条件的访问外部类的成员?

内部类是 java的一颗语法糖,编译之后会生成两个 class 文件,匿名内部类名字为:外部类名$x,成员内部类名字为:外部类名$内部类名,编译器会默认为成员内部类添加一个参数类型为指向外部类对象的构造方法。

  1. 为什么局部内部类和匿名内部类只能访问局部 final 变量?

比如我们在一个方法内写了一个 Thread 匿名内部类,当外部的方法执行完 毕后,方法内的局部变量生命周期结束,而 Thread 对象的生命周期还没有结束,所以必须使用 final 修改外部类的局部变量以使它在编译阶段就被放入常量池当中。

  1. .this 与 .new

当我们需要实例化一个成员内部类的时候,可以通过 OuterClass.new InnerClass 的方式初始化;

如果我们需要在内部类中生成对外部类对象的引用 可以使用 OuterClassName.this。

数组详解

      数组的本质还是一个对象,操作数组就是操作指向该数组对象的引用;

String字符串:

      一个String字符串本身属性是final的,不能改变的,但是指向它的指针的属性是可以改变的——即当需要改变它的内容的时候会返回一个新对象;

      eg: String str = new String("abc");

      例子中字符串“abc”本身的属性是不能改变的,但是其指针str是可以改变的。

      String对 + 运算符的重载实际上是使用StringBuilder.append()创建了一个新的String对象;

String 为什么设计成不可变对象?

源码分析:

public final class String  // 不能被继承

implements java.io.Serializable, Comparable<String>, CharSequence {      

/** The value is used for character storage. */      

private final char value[];      

/** Cache the hash code for the string */      

private int hash; // Default to 0

包含两个成员变量:value:String 的字符序列;hash:该 String 对象 hash 值 的缓存。我们通过普通代码对一个 String 的改变都是通过返回一个新的 String 对 象来完成的。但是 String 也不是绝对不可变的,我们可以通过反射拿到 value 对 象,然后改变它。 (final 域是不能修改的,但是如果 final 域指向的对象是可变的, 我们就可以修改 final 域指向对象的内容)

设计成不可变对象的好处

1. 因为它是不可变的,所以其 hashCode()永远保持一致,也就是每次在使 用一个 String 对象的 hashCode 的时候都不用重新计算,直接返回 hash 值即可,效率更高;

2. 不可变对象天生线程安全,可以无需同步的在多个线程间共享;

3. 安全性,常用于数据库连接、网络连接、打开文件等,避免了参数修改。

      StringBuilder可变字符串,线程不太安全,但效率高,推荐使用;

      StringBuffer可变字符串,线程安全,但效率低,不推荐使用;

三者执行速度上:StringBuilder > StringBuffer > String

Integer缓存处理详解

      [-128,127]之间的数,仍然当作基本数据类型(比对象的处理速度快)来处理;

      eg:若int a=1234;int b=1234;则代码a==b与a.equals(b)的结果不同:

      "==":比较的是指向该变量的地址;——return false;

      equals函数:比较的是两个变量的值;——return true;

      若上例中a和b处于[-128,127]之间,则"=="和equals均返回true;

集合与容器Collection详解:

1.集合只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类型都有对应的引用类型;

2.集合存放的是对各对象的引用,对象背身还是放在对内存中;

3.集合可以存放不同类型,不限数量的数据类型;

迭代器/游标iterator:

为容器遍历而生——提供遍历容器对象中各个元素的方法;类似于公交车上的售票员——关注公交车上的每个乘客;

通常分为三个步骤:获取迭代器对象、先检查、再获取

ArrayList<String> list = new ArrayList<String>();

list.add(“马云”);

list.add(“马化腾”);

//1、根据容器获取迭代器对象
Iterator<String> it = list.iterator();
//2、检查是否 存在下一个元素
while( it.hasNext() ){

      //3、内部移动游标,获取元素
          String element=it.next();

//…其他处理
}

容器相关详解:

      ArrayList底层实现是数组,查询快,增删慢;线程不安全效率高;

LinkedList底层实现是链表,查询慢,增删快;线程不安全效率高;

Vector线程安全,效率低;

  

HashMap:键值对(key-value)详解:

      通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value

原文地址:https://www.cnblogs.com/panweiwei/p/11909020.html