java小白的一点总结!!!
一:JAVA概述
1. Java的三种技术架构:
1) JAVAEE: Java Platform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发;
2) JAVASE: Java Platform Standard Edition,完成桌面应用程序的开发,是其它两者的基础;
3) JAVAME: Java Platform Micro Edition,开发电子消费产品和嵌入式设备,如手机中的程序;
2. JDK:
Java Development Kit, java的开发工具包和运行环境, java的开发工具和jre.
3. JRE
Java Runtime Environment, java程序的运行环境, java运行的所需的类库+JVM(java虚拟机).
4. 配置环境变量:
a) 让操作系统在任意的位置都可以运行java的jdk的根目录下的bin目录下的工具.环境变量的配置:
1) 永久配置方式:
path=java的jdk的根目录\bin
2) 临时配置方式:
set path=%path%;C:\Program Files\Java\jdk\bin
特点:系统默认先去当前路径下找要执行的程序,如果没有,再去path中设置的路径下找.
3) classpath的配置:
1): 永久配置方式: 在环境变量中配置:classpath=.;
2): 临时配置方式: set classpath=.;c:\;e:\
//还有一种方式是创建 JAVA_HOME,将bin目录路径放进去,方法很多,自己选择。
注意: 在定义classpath环境变量时, 需要注意的情况
如果没有定义环境变量classpath, java启动jvm后,会在当前目录下查找要运行的类文件;
如果指定了classpath,那么会在指定的目录下查找要运行的类文件.
还会在当前目录找吗?两种情况:
1): 如果classpath的值结尾处有分号,在具体路径中没有找到运行的类,会默认在当前目录再找一次.
2): 如果classpath的值结果处没有分号,在具体的路径中没有找到运行的类,不会再当前目录找.
一般不指定分号,如果没有在指定目录下找到要运行的类文件,就报错,这样可以调试程序.
5. javac命令和java命令在cmd中运行:
当你是一位初学者时,建议你使用记事本之类的编辑器进行程序编写,然后在cmd中执行。
要知道java是分两部分的:一个是编译,一个是运行.
javac: 负责的是编译的部分,当执行javac时,会启动java的编译器程序.对指定扩展名的.java文件进行编译.生成了jvm可以识别的字节码文件.也就是class文件,也就是java的运行程序.
java: 负责运行的部分.会启动jvm.加载运行时所需的类库,并对class文件进行执行.
一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main方法.
6.关于java是如何跨平台的:
首先,java源文件由编译器编译成中间字节码文件(class文件),class文件是能够被java虚拟机(JVM)识别并运行的二进制文件。编译后的class文件在JVM中运行,不同的计算机平台拥有不的JVM,比如Windows操作系统中拥有Windows平台下的JVM,Unix平台拥有Unix平台下的JVM,这些不同的平台下的JVM可以执行相同的class文件。因此经过编译的Java源程序可以运行在任何平台的JVM中,并且无需重新编译。这就是Java的平台无关性,即:java的跨平台性。
二.java基础语法
1.变量与表达式:
1) java中的数据类型分为两大类,基本数据类型和引用数据类型。
它们的区别:基本类型的变量中存储的是真实数据,引用类型变量中存储的是内存地址编号。
2)基本数据类型&引用数据类型;
3)声明变量(驼峰命名法):
变量是指在程序运行过程中其值可以改变的量。
(1)不能以数字开头,是以数字,字母,美元符号,下划线组成;
(2)不能是拼音或a、b、c这样的字眼;
(3)不能和Java关键字重复;
(4)见名知义。
4)表达式:运算符和操作数的有效组合,操作数可以是变量,常量,方法调用返回值。
5)类型强制转换:
自动转换:由低级别的数据类型转换为高级数据类型的时候,可自动转换。
强制转换:由高级别的数据类型转换为低级数据类型的时候,需要强制转换。
强制转换方法: (目标类型)表达式
如: long pt=598895;
Int a=(int)pt;
3.分支结构
1)if,else if,else:此三者需要熟悉掌握,毕竟在日后的应用中经常要用到。
2)switch(表达式){ case 常量1: break; ... } 3)continue与break区别: break出现时代表着直接退出循环,而continue表示退出此次循环。 4.循环结构 1)for、do...while、while2)for循环适合知道循环次数的循环、while循环适合先判断条件,
再执行循环体的循环、do循环适合先执行循环体,再判断条件的循环。
5.数组
数组:就是相同数据类型的元素按一定顺序排列的组合。 数组元素:数组中的一个值。 数组大小:数组中的元素个数就是数组的大小。 如何获取数组大小:每个数组都有一个length属性,用来获取数组大小。 如:int[] a=new int[4]; Int len=a.length; 什么是数组下标:数组中的下标代表数据中的元素,从0开始的数值,0代表第一个元素,1代表第二个元素,以此类推。 如:int[] a=new int[]{1,2,5,9}; System.out.println(a[3]);//代表打印第四个元素9 |
6.方法:
为了提高代码的复用性, 可以将其定义成一个单独的功能,
该功能的体现就是java中的方法. 方法就是体现之一.
java中的方法的定义格式:
修饰符 返回值类型 方法名([参数类型 形式参数1[, 参数类型 形式参数1, …]]){
执行语句;
[return 返回值;]
}
当方法没有具体的返回值时, 返回的返回值类型用void关键字表示.
如果方法的返回值类型是void时, return语句可以省略不写的, 系统会帮你自动加上.
return的作用: 结束方法. 结束功能.
如何定义一个方法?
方法其实就是一个功能, 定义方法就是实现功能, 通过两个明确来完成:
1)、明确该功能的运算完的结果, 其实是在明确这个方法的返回值类型.
2)、在实现该功能的过程中是否有未知内容参与了运算, 其实就是在明确这个方法的参数列表(参数类型&参数个数).
方法的作用:
1)、用于定义功能.
2)、用于封装代码提高代码的复用性.
注意: 方法中只能调用方法, 不能定义方法.
主方法:
1)、保证该类的独立运行.
2)、因为它是程序的入口.
3)、因为它在被jvm调用.
方法定义名称是为什么呢?
大家学习java的时候老师肯定说过, 见名知意, 方便于调用. 增加代码的阅读性.
方法重载: 在一个类中, 如果出现了两个或者两个以上的同名方法, 只要它们的参数的个数, 或者参数的类型, 参数顺序不同, 即可称之为该方法重载了. (overload)
如何区分重载: 如果方法名相同时, 只看参数列表. 和返回值类型没关系.
*作为java中的重点,对于方法的学习大家应该掌握以下几点:
(1)会定义和使用方法
(2)理解变量的作用于以及生命周期
(3)理解形式参数和实际参数
(4)会快速调用方法以及合理使用返回值
7.必须会的冒泡排序
冒泡排序 | int nums[] =new int[]{16,25,13,87,34}; int temp; for(int i=0;i<nums.length-1;i++){ for(int
j=0;j<nums.length-1-i;j++){ if(nums[j]>nums[j+1]){ temp= nums[j]; nums[j]= nums[j+1]; nums[j+1]=temp; } } } |
boolean | equals(String) | 比较俩个字符串是否相等 |
boolean | equalsIgnoreCase(String) | 忽略大小比较字符串是否相等 |
int | length() | 获取字符串长度 |
String | toLowerCase() | 获取小写字符串 |
String | toUpperCase() | 获取大写字符串 |
boolean | startsWith(String) | 在原字符串中是否以传入字符串开头 |
boolean | endsWith(String) | 在原字符串中是否以传入字符串结尾 |
String | charAt(int) | 获取字符串中的一个字符 |
int | indexOf(String) | 判断字符串在原字符串中第一次出现的位置 |
int | lastindexOf(String) | 判断字符串在原字符串最后一次出现的位置 |
int | compareTo(String) | 比较俩个字符串的大小 |
String | substring(int) | 从字符串开头截取到最后 |
String | Substring(int,int) | 从传入第一个截取到传入最后一个 |
String | trim() | 清空字符串空白 |
String[] | split(String) | 将字符串分割成字符串数组 |
String | replace(String) | 将传入字符串替换成指定字符串 |
1)关于对象,我们经常说的是万物皆对象,也就是说,看得见摸得着任何东西都是对象,对象是具体的概念。
2)类:先有类后有对象,类是具有相同状态和行为的一组对象的集合。类是用来规定对象的。
3)对象和类都占有内存,使用对象时,先要加载类,则类就会常驻内存。
过程和对象在我们的程序中是如何体现的呢?过程其实就是方法;对象是将方法等一些内容进行了封装.
匿名对象使用场景: 当对方法只进行一次调用的时候, 可以使用匿名对象.
在类中定义其实都称之为成员. 成员目前就两种:
1: 成员变量: 其实对应的就是事物的属性.
2: 成员方法: 其实对应的就是事物的行为.
所以, 其实定义类, 就是在定义成员变量和成员方法. 但是在定义前, 必须先要对事物进行属性和行为的分析, 才可以用代码来体现.
private int age;//私有的访问权限最低, 只有在本类中的访问有效.
注意: 私有仅仅是封装的一种体现形式而已.
私有的成员: 其他类不能直接创建对象访问, 所以只有通过本类对外提供具体的访问方式来完成对私有的访问, 可以通过对外提供方法的形式对其进行访问.
好处: 可以在方法中加入逻辑判断等操作, 对数据进行判断等操作.
总结: 属性是用于存储数据的, 直接被访问, 容易出现安全隐患, 所以, 类中的属性通常被私有化, 并对外提供公共的访问方法.
这个方法一般有两个, 规范写法: 对于属性 xxx, 可以使用setXXX(),getXXX()对其进行操作.
类中怎么没有定义主方法呢?
注意: 主方法的存在, 仅为该类是否需要独立运行, 如果不需要, 主方法是不用定义的.
主方法: 保证所在类的独立运行, 是程序的入口, 被jvm调用.
成员变量和局部变量的区别:
1: 成员变量直接定义在类中.
局部变量定义在方法中, 参数上, 语句中.
2: 成员变量在这个类中有效.
局部变量只在自己所属的大括号内有效, 大括号结束, 局部变量失去作用域.
3: 成员变量存在于堆内存中, 随着对象的产生而存在, 消失而消失.
局部变量存在于栈内存中, 随着所属区域的运行而存在, 结束而释放.
构造方法: 用于初始化当前对象, 它具有针对性, 方法的一种.
特点:
1: 该方法的名称和所在类的名称相同.
2: 不需要定义返回值类型.
3: 该方法不用具体的返回值.
记住: 所有对象创建时, 都需要初始化才可以使用.
注意事项: 一个类在定义时, 如果没有定义过构造方法, 那么该类中会自动生成一个空参数的构造方法, 为了方便该类创建对象, 完成初始化. 如果在类中自定义了构造方法, 那么默认的构造方法就没有了.
一个类中, 可以有多个构造方法, 因为它们的方法名称都相同, 所以只能通过参数列表来区分. 所以, 一个类中如果出现多个构造方法. 它们的存在是以重载体现的.
构造方法和一般方法有什么区别呢?
1: 两个方法定义格式不同.
2: 构造方法是在对象创建时, 就被调用, 用于初始化, 而且初始化动作只执行一次.
一般方法, 是对象创建后, 需要调用才执行, 可以被调用多次.
什么时候使用构造方法呢?
分析事物时, 发现具体事物一出现, 就具备了一些特征, 那就将这些特征定义到构造方法内.
Person p = new Person();
创建一个对象都在内存中做了什么事情?
1: 先将硬盘上指定位置的Person.class文件加载进内存.
2: 执行main方法时, 在栈内存中开辟了main方法的空间(压栈-进栈), 然后在main方法的栈区分配了一个变量p.
3: 在堆内存中开辟一个实体空间, 分配了一个内存首地址值.
4: 在该实体空间中进行属性的空间分配, 并进行了默认初始化.
5: 对空间中的属性进行显示初始化.
6: 进行实体的构造代码块初始化.
7: 调用该实体对应的构造方法, 进行构造方法初始化.
8: 将首地址赋值给p , p变量就引用了该实体. (指向了该对象)
--------------------------------------------------------------------------------------------
*封 装: 是指隐藏对象的属性和实现细节, 仅对外提供公共访问方式.
好处: 将变化隔离;便于使用;提高重用性;安全性.
封装原则: 将不需要对外提供的内容都隐藏起来, 把属性都隐藏, 提供公共方法对其访问.
this:代表当前对象. 就是所在方法所属对象的引用.
this到底代表什么呢?哪个对象调用了这个方法, this就代表哪个对象, 就是哪个对象的引用.
开发时, 什么时候使用this呢?
在定义功能时, 如果该功能内部使用到了调用该功能的对象, 这时就用this来表示这个对象.
this 还可以用于构造方法间的调用.
调用格式: this(实际参数);
this对象后面跟上 . 调用的是成员属性和成员方法(一般方法);
this对象后面跟上 () 调用的是本类中的对应参数的构造方法.
注意: 用this调用构造方法, 必须定义在构造方法的第一行. 因为构造方法是用于初始化的, 所以初始化动作一定要执行. 否则编译失败.
static: 静态修饰符, 用于修饰成员(类变量和类方法).
特点:
1, 想要实现对象中的共性数据的对象共享. 可以将这个数据进行静态修饰.
2, 被静态修饰的成员, 可以直接被类名所调用. 也就是说, 静态的成员多了一种调用方式. 类名.静态方式.
3, 静态随着类的加载而加载. 而且优先于对象存在.
弊端:
1, 有些数据是对象特有的数据, 是不可以被静态修饰的. 因为那样的话, 特有数据会变成对象的共享数据. 这样对事物的描述就出了问题. 所以, 在定义静态时, 必须要明确, 这个数据是否是被对象所共享的.
2, 静态方法只能访问静态成员, 不可以访问非静态成员.
因为静态方法加载时, 优先于对象存在, 所以没有办法访问对象中的成员.
3, 静态方法中不能使用this, super关键字.
因为this代表对象, 而静态在时没有对象, 所以this无法使用.
4, 主方法是静态的.
什么时候定义静态成员呢?或者说: 定义成员时, 到底需不需要被静态修饰呢?
成员分两种:
1, 静态成员变量. (数据共享时静态化)
该成员变量的数据是否是所有对象都一样:
如果是, 那么该变量需要被静态修饰, 因为是共享的数据.
如果不是, 那么就说这是对象的特有数据, 要存储到对象中.
2, 静态成员方法. (方法中没有调用特有数据时就定义成静态)
如果判断成员方法是否需要被静态修饰呢?
只要参考, 该方法内是否访问了对象中的特有数据:
如果有访问特有数据, 那方法不能被静态修饰.
如果没有访问过特有数据, 那么这个方法需要被静态修饰.
成员变量和静态变量的区别:
1, 成员变量所属于对象. 所以也称为实例变量.
静态变量所属于类. 所以也称为类变量.
2, 成员变量存在于堆内存中.
静态变量存在于方法区中.
3, 成员变量随着对象创建而存在. 随着对象被回收而消失.
静态变量随着类的加载而存在. 随着类的消失而消失.
4, 成员变量只能被对象所调用 .
静态变量可以被对象调用, 也可以被类名调用.
所以, 成员变量可以称为对象的特有数据, 静态变量称为对象的共享数据.
静态的注意: 静态的生命周期很长.
静态代码块: 就是一个有静态关键字标示的一个代码块区域. 定义在类中.
作用: 可以完成类的初始化. 静态代码块随着类的加载而执行, 而且只执行一次(new 多个对象就只执行一次).
如果和主方法在同一类中, 优先于主方法执行.
Public: 访问权限最大.
static: 不需要对象, 直接类名即可.
void: 主方法没有返回值.
Main: 主方法特定的名称.
(String[] args): 主方法的参数, 是一个字符串数组类型的参数, jvm调用main方法时, 传递的实际参数是 new String[0].
jvm默认传递的是长度为0的字符串数组, 我们在运行该类时, 也可以指定具体的参数进行传递. 可以在控制台, 运行该类时,
在后面加入参数. 参数之间通过空格隔开. jvm会自动将这些字符串参数作为args数组中的元素, 进行存储.
静态代码块、构造代码块、构造方法同时存在时的执行顺序: 静态代码块 >>> 构造代码块 >>> 构造方法;
*继 承:
好处:
1: 提高了代码的复用性.
2: 让类与类之间产生了关系, 构成了另一个特征多态的前提.
父类的由来: 其实是由多个类不断向上抽取共性内容而来的.
java中对于继承, java类只支持单继承. java虽然不直接支持多继承, 但是保留了这种多继承机制, 进行改良.
单继承: 一个类只能有一个父类.
多继承: 一个类可以有多个父类.
Java支持多继承吗? 为什么不支持多继承呢?
Java类不支持多继承, 但是Java的接口支持多继承.
因为当一个类同时继承两个父类时, 两个父类中有相同的功能, 那么子类对象调用该功能时, 运行哪一个呢?因为父类中的方法中存在方法体.
但是java支持多重继承. A继承B B继承C C继承D.
多重继承的出现, 就有了继承体系. 体系中的顶层父类是通过不断向上抽取而来的. 它里面定义的该体系最基本最共性内容的功能.
所以, 一个体系要想被使用, 直接查阅该系统中的父类的功能即可知道该体系的基本用法. 那么想要使用一个体系时, 需要建立对象. 建议建立最子类对象, 因为最子类不仅可以使用父类中的功能. 还可以使用子类特有的一些功能.
简单说: 对于一个继承体系的使用, 查阅顶层父类中的内容, 创建最底层子类的对象.
子父类出现后, 类中的成员都有了哪些特点:
1: 成员变量.
SuperClass instance = new Subclass();
当子父类中出现一样的属性时, 子类类型的对象, 调用该属性, 值是该对象接收类的属性值.
需要注意的是 instance 不能访问到它自己的属性
this: 代表是本类类型的对象引用.
super: 代表是子类所属的父类中的内存空间引用.
注意: 子父类中通常是不会出现同名成员变量的, 因为父类中只要定义了, 子类就不用在定义了, 直接继承过来用就可以了.
2: 成员方法.
当子父类中出现了一模一样的方法时, 建立子类对象会运行子类中的方法. 好像父类中的方法被重写掉一样. 所以这种情况, 是方法的另一个特性: 重写(复写, 重写)
什么时候使用重写呢?当一个类的功能内容需要修改时, 可以通过重写来实现.
3: 构造方法.
发现子类构造方法运行时, 先运行了父类的构造方法. 为什么呢?
原因: 子类的所有构造方法中的第一行, 其实都有一条隐式的调用super();
super(): 表示父类的构造方法, 并会调用于参数相对应的父类中的构造方法. 而super():是在调用父类中空参数的构造方法.
为什么子类对象初始化时, 都需要调用父类中的方法?(为什么要在子类构造方法的第一行加入这个super()?)
因为子类继承父类, 会继承到父类中的数据, 所以必须要看父类是如何对自己的数据进行初始化的. 所以子类在进行对象初始化时, 先调用父类的构造方法, 这就是子类的实例化过程.
注意: 子类中所有的构造方法都会默认访问父类中的空参数的构造方法, 因为每一个子类构造内第一行都有默认的语句super();
如果父类中没有空参数的构造方法, 那么子类的构造方法内, 必须通过super语句指定要访问的父类中的构造方法.
如果子类构造方法中用this来指定调用子类自己的构造方法, 那么被调用的构造方法也一样会访问父类中的构造方法.
问题: super()和this()是否可以同时出现的构造方法中.
两个语句只能有一个定义在第一行, 所以只能出现其中一个.
super()或者this():为什么一定要定义在第一行?
因为super()或者this()都是调用构造方法, 构造方法用于初始化, 所以初始化的动作要先完成.
继承的细节:
什么时候使用继承呢?
当类与类之间存在着所属关系时, 才具备了继承的前提. a是b中的一种. a继承b. 狼是犬科中的一种.
英文书中, 所属关系: " is a "
注意: 不要仅仅为了获取其他类中的已有成员进行继承.
细节二:
在方法重写时, 注意两点:
1: 子类重写父类时, 必须要保证 子类方法的权限必须大于等于父类方法权限可以实现继承. 否则, 编译失败.
2: 重写时, 要么都静态, 要么都不静态. (其实静态方法是不存在重写的, 因为静态方法是类名调用的)
*多态:某一种事物有不同的具体的体现或者说是同一个事务的不同展现形态, 在
代码中体现为: 使用父类的变量接收子类的实例, 运行的时候展现的是子类实例的行为,还有一种, 使用接口的类型接收该接口的实现类的实例, 运行的时候表现出实现类的行为.
体现: 父类引用或者接口的引用指向了自己的子类对象. //Animal a = new Cat();
多态的好处: 提高了程序的扩展性.
多态的弊端: 当父类引用指向子类对象时, 虽然提高了扩展性, 但是只能访问父类中具备的方法, 不可以访问子类中特有的方法. (前期不能使用后期产生的功能, 即访问的局限性)
多态的前提:
1: 必须要有关系, 比如继承、或者实现.
2: 通常会有重写操作.
多态的出现思想上也做着变化: 以前是创建对象并指挥对象做事情. 有了多态以后, 我们可以找到对象的共性类型, 直接操作共性类型做事情即可, 这样可以指挥一批对象做事情, 即通过操作父类或接口实现.
--------------------------------------------------------------
class Arry{
void 讲课(){
System.out.println("企业管理");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class Keke extends Arry{
void 讲课(){
System.out.println("JAVA");
}
void 看电影(){
System.out.println("看电影");
}
}
class {
public static void main(String[] args) {
Arry x = new Keke(); //Keke老师对象被提升为了Arry老师类型.
// x.讲课();
// x.看电影(); //错误.
Keke老师 y = (Keke老师)x; //将Arry老师类型强制转换成Keke老师类型.
y.看电影();//在多态中, 自始自终都是子类对象在做着类型的变化.
}
}
---------------------------------------------------------------
如果想用子类对象的特有方法, 如何判断对象是哪个具体的子类类型呢?
可以可以通过一个关键字 instanceof ;//判断对象是否实现了指定的接口或继承了指定的类
格式: <对象 instanceof 类型> , 判断一个对象是否所属于指定的类型.
Student instanceof Person = true;//student继承了person类
多态在子父类中的成员上的体现的特点:
1, 成员变量: 在多态中, 子父类成员变量同名.
成员变量参考的都是引用变量所属的类中的成员变量.
2, 成员方法.
成员方法, 编译看引用型变量所属的类, 运行看对象所属的类.
--------------------------------------------------------------------------------------------
*抽象类和接口:
1)使用关键字abstract修饰的类成为抽象类,他不允许实例化。使用关键字abstract修饰的方法称为抽象方法
抽象方法只有方法头,没有方法体。
2)抽象类可以有子类,当他的子类继承抽象类后,必须实现抽象方法。
3)构造方法不允许声明为抽象方法。
4)从安全角度考虑,JAVA只允许单继承,但是接口可以实现多继承,接口是一组抽象方法和常量,与抽象类
相似,接口只声明抽象方法,不给出方法体。并且实现接口的类必须实现他的所有方法。接口中的方法必须是
public abstract,属性必须是public abstract final.
抽象类和接口的共性: 都是不断向上抽取的结果.
抽象类和接口的区别:
1: 抽象类只能被继承, 而且只能单继承.
接口需要被实现, 而且可以多实现.
2: 抽象类中可以定义非抽象方法, 子类可以直接继承使用.
接口中都有抽象方法, 需要子类去实现.
3: 抽象类使用的是 is a 关系.
接口使用的 like a 关系.
4: 抽象类的成员修饰符可以自定义.
接口中的成员修饰符是固定的. 变量:public static final, 方法: public abstract.
在开发之前, 先定义规则, A和B分别开发, A负责实现这个规则, B负责使用这个规则. 至于A是如何对规则具体实现的, B是不需要知道的. 这样这个接口的出现就降低了A和B直接耦合性.
10.异常处理:
异常:就是不正常。程序在运行时出现的不正常情况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操作问题以及处理问题。
出现的问题有很多种,比如数组下标越界(ArrayIndexOutOfBoundsException),空指针(NullPointerException)等都是。就对这些问题进行分类。而且这些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位置,所以可以不断的向上抽取。形成了异常体系。
--------java.lang.Throwable:
Throwable:可抛出的。
|--Error:错误,一般情况下,不编写针对性的代码进行处理,通常是jvm发生的,需要对程序进行修正。
|--Exception:异常,可以有针对性的处理方式
Ps:error和exception 的区别。是一个面试题。
error属于编译时错误,根本不会编译通过,也就是不会生成.class文件,exception属于运行时错误,只有在调用的时候才会报错,比如空指针或数组下标越界等等。
简单来说error想要恢复,比较困难,如内存溢出等。Exception只要是你的程序设计没有问题是不会出现的。
无论是错误还是异常,它们都有具体的子类体现每一个问题,它们的子类都有一个共性,就是都以父类名才作为子类的后缀名。
这个体系中的所有类和对象都具备一个独有的特点;就是可抛性。
可抛性的体现:就是这个体系中的类和对象都可以被throws和throw两个关键字所操作。
------------------------------------------------------
我们一般把异常分为两种:
1. 运行时异常: 编写代码的时候不会报异常, 但是运行的时候可能会: 10 / 0; 抛出时所在的方法可以不用throws声明;
2. 编译异常: 都是RuntimeException的直接或者间接子类,编写代码的时候就必须处理(try...catch...finally), 如: new FileInputStream(“nice.txt”); 如果出现异常需要使用throw抛出的话, 所在的方法必须使用 throws声明.
---------------------------------------------------------
异常处理原则:功能抛出几个异常,功能调用如果进行try处理,需要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。
特殊情况:try对应多个catch时,如果有父类的catch语句块,一定要放在下面。
编译时被检查的异常和运行时异常的区别:
编译被检查的异常在方法内被抛出,方法必须要声明,否编译失败。
声明的原因:是需要调用者对该异常进行处理。
运行时异常如果在方法内被抛出,在方法上不需要声明。
不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。
定义异常处理时,什么时候定义try,什么时候定义throws呢?
功能内部如果出现异常,如果内部可以处理,就用try;
如果功能内部处理不了,就必须声明出来,让调用者处理。
自定义异常:当开发时,项目中出现了java中没有定义过的问题时,这时就需要我们按照java异常建立思想,将项目的中的特有问题也进行对象的封装。这个异常,称为自定义异常。
对于除法运算,0作为除数是不可以的。java中对这种问题用ArithmeticException类进行描述。对于这个功能,在我们项目中,除数除了不可以为0外,还不可以为负数。可是负数的部分java并没有针对描述。所以我们就需要自定义这个异常。
自定义异常的步骤:
1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性。
2:通过throw 或者throws进行操作。
异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。
11.多线程:
进程:正在进行中的程序。其实进程就是一个应用程序运行时的内存分配空间。
线程:其实就是进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间的标示。线程负责的是应用程序的执行顺序。
一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区、自己的变量。
jvm在启动的时,首先有一个主线程,负责程序的执行,调用的是main方法。主线程执行的代码都在main方法中。
当产生垃圾时,收垃圾的动作,是不需要主线程来完成,因为这样,会出现主线程中的代码执行会停止,会去运行垃圾回收器代码,效率较低,所以由单独一个线程来负责垃圾回收。
随机性的原理:因为cpu的快速切换造成,哪个线程获取到了cpu的执行权,哪个线程就执行。
返回当前线程的名称:Thread.currentThread().getName()
线程的名称是由:Thread-编号定义的。编号从0开始。
线程要运行的代码都统一存放在了run方法(要么重写Thread中的run, 要么实现Runnable接口中的run)中。
线程要运行必须要通过类中指定的方法开启。start方法。(启动后,就多了一条执行路径)
start方法:1)、启动了线程;2)、让jvm调用了run方法。
创建线程的第一种方式:继承Thread ,由子类重写run方法。
步骤:
1,定义类继承Thread类;
2,目的是重写run方法,将要让线程运行的代码都存储到run方法中;
3,通过创建Thread类的子类对象,创建线程对象;
4,调用线程的start方法,开启线程,并执行run方法。
线程状态:
被创建:start()
运行:具备执行资格,同时具备执行权;
冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;
临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;
消亡:stop()
创建线程的第二种方式:实现一个接口Runnable。
步骤:
1,定义类实现Runnable接口。
2,重写接口中的run方法(用于封装线程要运行的代码)。
3,通过Thread类创建线程对象;
4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造方法。
为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
Ticket t = new Ticket();
/*
直接创建Ticket对象,并不是创建线程对象。
因为创建对象只能通过new Thread类,或者new Thread类的子类才可以。
所以最终想要创建线程。既然没有了Thread类的子类,就只能用Thread类。
*/
Thread t1 = new Thread(t); //创建线程。
/*
只要将t作为Thread类的构造方法的实际参数传入即可完成线程对象和t之间的关联
为什么要将t传给Thread类的构造方法呢?其实就是为了明确线程要运行的代码run方法。
*/
t1.start();
11.集合:用于储存对象的容器
*java中第二大重要的知识点;
特点:
1:对象封装数据,对象多了也需要存储。集合用于存储对象。
2:对象的个数确定可以使用数组,但是不确定怎么办?可以用集合。因为集合是可变长度的。
--< java.util >-- Collection接口:
Collection:
|--List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
|--Set:无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。
--< java.util >-- Iterator接口:
迭代器:是一个接口。作用:用于取集合中的元素。
--< java.util >-- List接口:
List本身是Collection接口的子接口,具备了Collection的所有方法。现在学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。
List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。
|--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。
|--Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。
--< java.util >-- Set接口:
Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。
|--HashSet:底层数据结构是哈希表,线程是不同步的。无序,高效;
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。
当元素的hashCode值相同时,才继续判断元素的equals是否为true。
如果为true,那么视为相同元素,不存。如果为false,那么存储。
如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
|--LinkedHashSet:有序,hashset的子类。
|--TreeSet:对Set集合中的元素的进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。
|--Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。
|--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable.
|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。
*Map(双列集合):
Map集合存储和Collection有着很大不同:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。
特点:要保证map集合中键的唯一性。
关于集合中的诸多方法,希望大家能够在API中自行查找,学会查找API才能正真把知识学到底。
在java知识中这部分也算是难点了,因为java语言中输入输出是以流的方式进行的,流是指计算机在输入、输出
操作中流动的数据序列。
-----------------------------------------------------------------------------------------*********************************总结************************************
还有一些知识是没有写到的,完了有时间在补充吧。都是一些简单的知识点归纳,方便日后翻阅,能力有限!!!