JAVA入门

时间:2024-01-12 19:53:08

编译型语言:高级语言代码经过编译器,一次性翻译为特定系统可以硬件执行的机器码,并包装成该平台所识别的可执行程序。

但是不同平台(系统)的机器码不同,所以编译后的可执行程序无法移植到其他平台。但是因为是机器码,所以执行效率高。

解释型语言:Ruby,pathon等,使用专门的解释器对源程序逐行编译并执行的语言。这样每次运行都需要进行编译,所以效率比较低,但是可移植性好,只需要特定平台的解释器就可以对源程序进行解释。

而java即使编译型也是解释型,会先将源码编译成一种平台无关的字节码即.class文件,而不是执行文件,再经过java解释器来解释执行。

负责解释执行的部分就是JVM,java虚拟机相当于虚拟的计算机,所有的java都是面向JVM的,JVM提供相同的一套接口给字节码,这样可以使所有的java编译后的字节码在任何平台上的JVM上通过这套接口运行,不同JVM向下解释为该特定平台的机器码并运行。

JDK:java标准版开发包:包含编译环境,java运行时环境(JRE),以及常用类库.JRE包含了JVM等java运行环境,

JAVA是一门纯粹面向对象的语言,所以其最小程序单元就是类,所有的程序部分必须在类中存在,不允许可执行语句或方法单独存在。

如果要某类能被解释器直接解释,则其必须包含public static void main(String[] args)作为入口

源文件命名:如果定义为public类,则该文件名必须与该类名一样。

一下:    char 2字节

byte 1字节  short 2字节   int  4字节  long 8字节    float 4字节    double 8字节

默认赋值,如果是整数类型,默认赋值为int 类型,如果是浮点型默认为double;赋值时没有进行声明可以赋给低位

但是如果是想把确定高位赋值给低位必须强制类型转换。

switch:允许byte ,short,int,char。javaSDK7以后允许string类型,不允许boolean类型

java关于循环的一个特殊点是代替GOTO的控制语句:

主要是使用一个标签,标签用:进行表示。

例子:这样就定义了一个标签outer,使用break或者continue就可以跳到其后所跟的标签的外层循环。

outer:

for(int i = 0 ; i < 5 ; i++){
  for (int j = 0 ; j < 3; j++) {
    System.out.println("i="+i+"j="+j );
    if(j == 1)
    continue outer;

  }
}

数组:java数组中只允许存放相同类型数据

一:静态初始化:初始化数组元素,

两种表示:一种是简化的,但是必须定义和初始化同时:

int[] numbers = {1,2,3,4,5};

二是标准的,可以定义和初始化分开:

int[] numbers;

numbers = new int[] {1,2,3,4,5}; 

二:动态初始化,只分配数组长度,元素值系统分配。

numbers = new int[length];

foreach循环:
for(type name : type[] | collection),但是name只是个临时变量,只能用来读取,不能用来改变元素的值    

静态内存池和使用new String()声明的区别:

字符串会由静态内存池来管理,直接声明相当于赋予了静态内存池中的字符串地址。

而如果要new String() "大大";来声明,这个字符还是交由静态内存池来管理,但是会声明一个string对象,我们声明的变量指向的是该string对象,该对象存放的字符串是由静态内存池来管理的。

面向对象:

对于static的方法来说,可以直接使用类来调用该方法,所以,在static方法中不能使用this,而且不能再static成员中访问非static成员。  

对于参数来说:形参中可以用…来表示可变参数。比如public static void test(int a , String… books);

这里就可以传入多个string作为参数,而且可以看到只有在参数的最后一个才能用可变参数,所以只可能有一个…参数。

方法重载:同一类的方法的方法名一样,但是参数列表不一样。   

**对于局部变量,除了形参外必须显示初始化。

对于java的类来说,为了防止不同类同名引入类似命名空间一样的包机制:

使用package 包名;就可以声明某类在某包下;

同一包下的类可以直接访问。不同包下的类需要使用包名.类名来使用。

比如:lee.MyClass a = new lee.MyClass();

如此比较麻烦,可以在类声明前使用import lee.MyClass来进行包导入。

使用构造器用来初始化实例,实际在new的时候系统已为该实例分配内存,构造器中this就可以使用该对象,只是该对象无法被外部访问。

构造器如果要调用另外一个构造器可以使用this.另外一个构造器。但是必须写在第一句。

当创建一个实例对象的时候,不仅会为该类成员变量分配内存,也会为其父类成员变量分配内存,即便子类定义父类相同变量名。

子类总会调用父类构造器。

类的第四个成员是初始化块:只有一个修饰符可以用就是static,使用static修饰的就是静态初始化块,这里当类进行初始化时会进行调用。普通初始化块当给实例对偶像分配内存,进行初始化时会隐式调用,调用在构造器之前。调用顺序,显示各个静态初始块从父到子类对类初始化,然后是各个普通初始化块和构造器从父到子对实例对象进行初始化。

一个变量声明为某个类对象是编译时,但是具体给该变量赋予类型是运行时决定的。

编译器在编译阶段只能调用其编译时所声明类型所具有的方法。但是运行时执行其运行时类型所具有方法。

比如Object p = new Person();p只能调用Object类所定义的方法,不能调用Person定义的方法,但是实际执行的是Person的方法。

但是引用实例变量时,其调用的是Object的变量,而不是运行时类型所定义的Person的变量。

如果要想p调用Person所定义方法,需要强制类型转换为Person类

final 修饰符:**该修饰符修饰的变量必须显示初始化

使用final修饰的变量当第一次初始化之后无法改变。所以需要注意,如果修饰了类变量或者成员变量,则如果在初始化代码块或者定义时或者构造器时没有显示初始化,则会被默认分配为0,null等初值,其后也不能更改,这样定义就毫无意义,所以,对于final修饰的成员变量或者 类变量,系统不会自动初始化,所以如果没有显示初始化则会报错,因为试图访问没有初始化的变量。所以规定:

类变量必须在静态初始化快或者声明时初始化。

成员变量必须在非静态初始化块或者声明变量时或者调用构造器时进行初始化。

****注意:所修饰变量如果为引用则只是改引用变量不能变,但是所引用的对象可以变化

***:如果所修饰的变量1声明时直接赋予了初始化值2该值初始化时就能确定下来,则再编译时不会声明该变量而是会将出现该变量的地方直接用初始值代替,相当于宏定义;

***:final修饰的方法不可以被重写,所以如果不希望自类重写的方法可以声明为final;

***:final修饰的类不能有子类。

抽象类:

有得有失:抽象类可以有抽象方法,有抽象方法的类必须得是抽象类;

1、抽象类不可以实例化   2、不能和static一起修饰,因为用static修饰的是静态方法,直接用改类调用,子类没办法重写,和static一起用没有意义   3、不能喝final合用,final修饰的类不能继承,修饰的方法不能重写,跟abstract修饰的需要被子类继承重写,冲突!。4、不能和private一起用;他需要被子类重写,private子类没办法获得。如果父类方法修饰为private,子类声明跟此方法一样名字的也只是自己重新声明一个方法,并不会重写。

看一下new String("hello") 然后再 "hello"是否相等。

接口:抽象类实际上是多个类具体抽象出来的共有模板。interface interfaceNmae;

那么将抽象类进行的更加具体,所有的方法都是抽象方法,没有普通方法就是接口。

***1、所有的变量或者方法是为了让类实现,修饰符只有public 和默认包访问权限。

2、会为普通无修饰符变量自动增加public static final,接口中变量只能是静态常量。

3、会为方法自动增加abstract public

4、接口没有构造器和普通成员变量 ,抽象类有,但是只是为了子类调用来初始化抽象类

****接口是一种规范,定义了实现者必须提供的方法,也就是规定了调用者该如何调用这些方法,(类似接口,双方相匹配才能插入)

内部类:

1、非静态内部类:可以用4个修饰符修饰。

内部类中使用变量,首先看方法体内局部变量,然后看内部类实例变量,最后看外部类变量。

如果要用外部类变量,需要用外部类名.this.变量名。

非静态内部类中不允许定义静态成员。

2、匿名内部类:

new 接口名()或者类构造器(){抽象方法实现.}

****要求匿名内部类访问的变量必须用final修饰.

3、匿名类的简单访问:Lambda;

这个为函数式接口提供简单构造实现。

参数->{方法体};

使用这个将会自动返回接口或者抽象类实例.

枚举类:enum ,同class和interface地位相同。是一种特殊的类。

1、枚举类的第一行内要定义所有枚举变量,

enum Season{

  SPRING,SUMMER,AUTURM,WINTER;//以这样为例,每个变量间用","分开。列出的这些变量会默认增加public static final。

  public String name;//同正常类一样,枚举类也可以声明变量和方法.这个name就是个变量。

}

2、所定义的非抽象枚举类会默认声明为final,所有枚举类不能派生子类。

3、如果构造器带参数,那么定义枚举变量时应显示定义其传入参数,如:

male("男"),female(“女”);

垃圾回收机制:
1、只是回收堆内存中没有被引用的对象。不能精准控制何时回收

2、对象要被回收时会调用finalize()方法。

对象主要3种状态,可达状态(有变量子啊引用),可恢复状态(无变量在引用,但未调用finalize,还可以在该方法中重新被引用成为可达),不可恢复状态(finalize调用后仍不可达,此时系统会真正回收该对象)

4总引用类型.

StongReference,softReference(比weak权限高,当内存足的时候,不会被收回,当内存不足的时候,可能会回收),WeakReference(只要gc运行,就会回收)

PhantomReference(虚引用,要求和引用队列联合使用,类似完全没有引用,当引用对象被回收前,虚引用会被添加到引用队列中)

JAVA基本框架:

System类:

1、可以访问系统变量和环境变量:System.getenv();System.getProperties();

2、输入输出,.in(如果是System.in则为键盘输入,否则可以输入File) , .out()

Runtime类:

可以获取当前系统的运行时环境,所以可以访问JVM信息,如处理器数量,内存情况等。

字符串类:String,StringBuffer,StringBuilder;

String是不可变类,后面两种是可变类,但是StringBuilder是线程不安全的,所以性能高一些

Locale:本地化类:主要思想就是语言友善化,各国家根据当地本地语言自动反馈出来。

创建多个properties文档,进行key-Value描述,然后根据不同的locale来读取相应的properties。

主要使用类就是ResourceBundle.getBundle(baseName//这个主要是用于确定要读取的properties文件,mylocale//这个用于确定相应的本地化类,其中确定国家,语言等信息).

Format类:2个重要的子类,DateFormat和NumberFormat

这两个都是抽象类,无法通过构造器来进行实例化,可以通过getDateInstance()等类方法实例化,

可以通过DateFormat df  = DateFormat.getDateInstance(日期类型,locale//本地化),来创建符合本地化的日期实例,然后通过df.format(date//某个确切时间对象)来显示。format对象2个方法,一个format()方法可以将对象转成字符串,一个parse(),可以将字符串转为Number或者日期.

例:String time = "2014-3-1";

System.out.println(DateFormat.getDateInstance().parse(time));

但是使用DateFormat必须使用相应格式才能转换,所以比较僵硬,如果想用任意格式的话需要使用SimpleDateFormat;

容器:Collection (set,queue,list),Map;

迭代:1、lambda:接口Iterable有个forEach(Consumer action)默认方法,其中Consumer是个函数式接口。而Iterable是Collection的父类,所以Collection也可以调用该方法。

Collection c = new HashSet();

c.forEach(obj->System.out.println(obj));

forEach方法会将容器中所有元素一个个传递给Consumer类的accept(T t)抽象方法,所以可以利用lambda来实现.

2、使用iterator类。

使用其中hasNext()等方法,需要注意!!!!使用iterator的遍历的时候不能改变容器的元素,否则会出现异常。

3、使用java5之后提供的foreach方法。

for(Object obj : collections){*****};

java8新增删除元素方法:removeIf(Predicate filter);Predicate同Consumer类一样,是个函数式接口。

Set:HashSet,最普通的set,结构是hash表。

LinkedHashSet:有顺序的set,按照添加进容器的顺序来决定存储位置。

TreeSet:是一种有序set,所以提供一下几个方法:Comparator comparator():如果采用了定制排序,则返回所使用的comparator。

first(),last()。返回第一个或者最后一个元素.

Object lower(Object e);

Object higher(Object e);返回比e元素后面或者前面的一个元素.

使用的是红黑树来存储.

使用TreeSet的话,放入其中的元素应该是同一类,否则无法比较,并且该类应该事先Comparable接口,里面与compareTo(Object obj)方法,实现该方法进行元素比较.

TreeSet判断元素相同与否只通过该元素的compareTo(Object obj).方法。

泛型:泛型的创建主要是为了集合,集合创建时为了成为某个集合实例的容器,所以创建时希望所有类都能放入,都是Object类型。

但是这样有些弊端,比如我这个集合就是为了放入Dog类集合,但是你却能放入Cat类进去。还有就是取出来的元素都是Object类,要转换成Dog类才能用。

使用方法:集合或者类后跟<类型>比如:List<String>,这样声明的不是任何类型的一个集合,而是一个String类型的集合。

Java7之前初始化时必须:List<String> list = new ArrayList<String>();

但是这样红色地方就很蠢,所以Java7以后允许使用棱型语句:List<String> list = new ArrayList<>();

****根普通我们以为的如数组:String[] strs ;  Object[] obj;  obj = strs;可以这样赋值,obj是String的子类;

而List<String>和List<Object> 没有任何关系,不能赋值。

如果希望有类似上述数组效果,就需要使用通配符:List<?>这样可以通配类型。List<? extends A>