写代码:java
1,明确需求。我要作什么?linux
2,分析思路。我要怎么作?1,2,3。web
3,肯定步骤。每个思路部分用到哪些语句,方法,和对象。算法
4,代码实现。用具体的java语言代码把思路体现出来。express
学习新技术的四点:编程
1,该技术是什么?windows
2,该技术有什么特色(使用注意):设计模式
3,该技术怎么使用。demo数组
4,该技术何时用?test。缓存
-----------------------------------------------------------------------------------------------
一:java概述:
1991 年Sun公司的James Gosling(詹姆斯·高斯林)等人开始开发名称为 Oak 的语言,但愿用于控制嵌入在有线电视交换盒、PDA等的微处理器;
1994年将Oak语言改名为Java;
Java的三种技术架构:
JAVAEE:Java Platform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发;
JAVASE:Java Platform Standard Edition,完成桌面应用程序的开发,是其它二者的基础;
JAVAME:Java Platform Micro Edition,开发电子消费产品和嵌入式设备,如手机中的程序;
1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具和jre。
2,JRE:Java Runtime Environment,java程序的运行环境,java运行的所需的类库+JVM(java虚拟机)。
3,配置环境变量:让java jdk\bin目录下的工具,能够在任意目录下运行,缘由是,将该工具所在目录告诉了系统,当使用该工具时,由系统帮咱们去找指定的目录。
环境变量的配置:
1):永久配置方式:JAVA_HOME=%安装路径%\Java\jdk
path=%JAVA_HOME%\bin
2):临时配置方式:set path=%path%;C:\Program Files\Java\jdk\bin
特色:系统默认先去当前路径下找要执行的程序,若是没有,再去path中设置的路径下找。
classpath的配置:
1):永久配置方式:classpath=.;c:\;e:\
2):临时配置方式:set classpath=.;c:\;e:\
注意:在定义classpath环境变量时,须要注意的状况
若是没有定义环境变量classpath,java启动jvm后,会在当前目录下查找要运行的类文件;
若是指定了classpath,那么会在指定的目录下查找要运行的类文件。
还会在当前目录找吗?两种状况:
1):若是classpath的值结尾处有分号,在具体路径中没有找到运行的类,会默认在当前目录再找一次。
2):若是classpath的值结果出没有分号,在具体的路径中没有找到运行的类,不会再当前目录找。
通常不指定分号,若是没有在指定目录下找到要运行的类文件,就报错,这样能够调试程序。
4,javac命令和java命令作什么事情呢?
要知道java是分两部分的:一个是编译,一个是运行。
javac:负责的是编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译。 生成了jvm能够识别的字节码文件。也就是class文件,也就是java的运行程序。
java:负责运行的部分.会启动jvm.加载运行时所需的类库,并对class文件进行执行.
一个文件要被执行,必需要有一个执行的起始点,这个起始点就是main函数.
----------------------------------------------------------------------------------------------
二:java语法基础:
1,关键字:其实就是某种语言赋予了特殊含义的单词。
保留字:其实就是尚未赋予特殊含义,可是准备往后要使用过的单词。
2,标示符:其实就是在程序中自定义的名词。好比类名,变量名,函数名。包含 0-九、a-z、$、_ ;
注意:
1),数字不能够开头。
2),不可使用关键字。
3,常量:是在程序中的不会变化的数据。
4,变量:其实就是内存中的一个存储空间,用于存储常量数据。
做用:方便于运算。由于有些数据不肯定。因此肯定该数据的名词和存储空间。
特色:变量空间能够重复使用。
何时定义变量?只要是数据不肯定的时候,就定义变量。
变量空间的开辟须要什么要素呢?
1,这个空间要存储什么数据?数据类型。
2,这个空间叫什么名字啊?变量名称。
3,这个空间的第一次的数据是什么? 变量的初始化值。
变量的做用域和生存期:
变量的做用域:
做用域从变量定义的位置开始,到该变量所在的那对大括号结束;
生命周期:
变量从定义的位置开始就在内存中活了;
变量到达它所在的做用域的时候就在内存中消失了;
数据类型:
1):基本数据类型:byte、short、int、long、float、double、char、boolean
2):引用数据类型: 数组、类、接口。
级别从低到高为:byte,char,short(这三个平级)-->int-->float-->long-->double
自动类型转换:从低级别到高级别,系统自动转的;
强制类型转换:什么状况下使用?把一个高级别的数赋给一个别该数的级别低的变量;
运算符号:
1)、算术运算符。
+ - * / % %:任何整数模2不是0就是1,因此只要改变被模数就能够实现开关运算。
+:链接符。
++,--
2)、赋值运算符。
= += -= *= /= %=
3)、比较运算符。
特色:该运算符的特色是:运算完的结果,要么是true,要么是false。
4)、逻辑运算符。
& | ^ ! && ||
逻辑运算符除了 ! 外都是用于链接两个boolean类型表达式。
&: 只有两边都为true结果是true。不然就是false。
|:只要两边都为false结果是false,不然就是true
^:异或:和或有点不同。
两边结果同样,就为false。
两边结果不同,就为true.
& 和 &&区别: & :不管左边结果是什么,右边都参与运算。
&&:短路与,若是左边为false,那么右边不参数与运算。
| 和|| 区别:|:两边都运算。
||:短路或,若是左边为true,那么右边不参与运算。
5)、位运算符:用于操做二进制位的运算符。
& | ^
<< >> >>>(无符号右移)
练习:对两个变量的数据进行互换。不须要第三方变量。
int a = 3,b = 5;-->b = 3,a = 5;
a = a + b; a = 8;
b = a - b; b = 3;
a = a - b; a = 5;
a = a ^ b;//
b = a ^ b;//b = a ^ b ^ b = a
a = a ^ b;//a = a ^ b ^ a = b;
练习:高效的算出 2*8 = 2<<3;
5,语句。
If switch do while while for
这些语句何时用?
1)、当判断固定个数的值的时候,可使用if,也可使用switch。
可是建议使用switch,效率相对较高。
switch(变量){
case 值:要执行的语句;break;
…
default:要执行的语句;
}
工做原理:用小括号中的变量的值依次和case后面的值进行对比,和哪一个case后面的值相同了
就执行哪一个case后面的语句,若是没有相同的则执行default后面的语句;
细节:1):break是能够省略的,若是省略了就一直执行到遇到break为止;
2):switch 后面的小括号中的变量应该是byte,char,short,int四种类型中的一种;
3):default能够写在switch结构中的任意位置;若是将default语句放在了第一行,则无论expression与case中的value是否匹配,程序会从default开始执行直到第一个break出现。
2)、当判断数据范围,获取判断运算结果boolean类型时,须要使用if。
3)、当某些语句须要执行不少次时,就用循环结构。
while和for能够进行互换。
区别在于:若是须要定义变量控制循环次数。建议使用for。由于for循环完毕,变量在内存中释放。
break:做用于switch ,和循环语句,用于跳出,或者称为结束。
break语句单独存在时,下面不要定义其余语句,由于执行不到,编译会失败。当循环嵌套时,break只跳出当前所在循环。要跳出嵌套中的外部循环,只要给循环起名字便可,这个名字称之为标号。
continue:只做用于循环结构,继续循环用的。
做用:结束本次循环,继续下次循环。该语句单独存在时,下面不能够定义语句,执行不到。
6,函 数:为了提升代码的复用性,能够将其定义成一个单独的功能,该功能的体现就是java中的函数。函数就是体现之一。
java中的函数的定义格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数1,…){
执行语句;
return 返回值;
}
当函数没有具体的返回值时,返回的返回值类型用void关键字表示。
若是函数的返回值类型是void时,return语句能够省略不写的,系统会帮你自动加上。
return的做用:结束函数。结束功能。
如何定义一个函数?
函数其实就是一个功能,定义函数就是实现功能,经过两个明确来完成:
1)、明确该功能的运算完的结果,实际上是在明确这个函数的返回值类型。
2)、在实现该功能的过程当中是否有未知内容参与了运算,其实就是在明确这个函数的参数列表(参数类型&参数个数)。
函数的做用:
1)、用于定义功能。
2)、用于封装代码提升代码的复用性。
注意:函数中只能调用函数,不能定义函数。
主函数:
1)、保证该类的独立运行。
2)、由于它是程序的入口。
3)、由于它在被jvm调用。
函数定义名称是为何呢?
答:1)、为了对该功能进行标示,方便于调用。
2)、为了经过名称就能够明确函数的功能,为了增长代码的阅读性。
重载的定义是:在一个类中,若是出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不一样,便可称之为该函数重载了。
如何区分重载:当函数同名时,只看参数列表。和返回值类型不要紧。
7,数 组:用于存储同一类型数据的一个容器。好处:能够对该容器中的数据进行编号,从0开始。数组用于封装数据,就是一个具体的实体。
如何在java中表现一个数组呢?两种表现形式。
1)、元素类型[] 变量名 = new 元素类型[元素的个数];
2)、元素类型[] 变量名 = {元素1,元素2...};
元素类型[] 变量名 = new 元素类型[]{元素1,元素2...};
---------------------------------------------------------
//二分查找法。必须有前提:数组中的元素要有序。
public static int halfSeach_2(int[] arr,int key){
int min,max,mid;
min = 0;
max = arr.length-1;
mid = (max+min)>>1; //(max+min)/2;
while(arr[mid]!=key){
if(key>arr[mid]){
min = mid + 1;
}
else if(key<arr[mid])
max = mid - 1;
if(max<min)
return -1;
mid = (max+min)>>1;
}
return mid;
}
---------------------------------------------------------
java分了5片内存。
1:寄存器。2:本地方法区。3:方法区。4:栈。5:堆。
栈:存储的都是局部变量 ( 函数中定义的变量,函数上的参数,语句中的变量 );
只要数据运算完成所在的区域结束,该数据就会被释放。
堆:用于存储数组和对象,也就是实体。啥是实体啊?就是用于封装多个数据的。
1:每个实体都有内存首地址值。
2:堆内存中的变量都有默认初始化值。由于数据类型不一样,值也不同。
3:垃圾回收机制。
----------------------------------------------------------------------------------------------
三:面向对象:★★★★★
特色:1:将复杂的事情简单化。
2:面向对象将之前的过程当中的执行者,变成了指挥者。
3:面向对象这种思想是符合如今人们思考习惯的一种思想。
过程和对象在咱们的程序中是如何体现的呢?过程其实就是函数;对象是将函数等一些内容进行了封装。
匿名对象使用场景:
1:当对方法只进行一次调用的时候,可使用匿名对象。
2:当对象对成员进行屡次调用时,不能使用匿名对象。必须给对象起名字。
在类中定义其实都称之为成员。成员有两种:
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:在堆内存中开辟一个实体空间,分配了一个内存首地址值。new
4:在该实体空间中进行属性的空间分配,并进行了默认初始化。
5:对空间中的属性进行显示初始化。
6:进行实体的构造代码块初始化。
7:调用该实体对应的构造函数,进行构造函数初始化。()
8:将首地址赋值给p ,p变量就引用了该实体。(指向了该对象)
--------------------------------------------------------------------------------------------
封 装(面向对象特征之一):是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离;便于使用;提升重用性;安全性。
封装原则:将不须要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
This:表明对象,就是所在函数所属对象的引用。
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数组中的元素,进行存储。
静态代码块、构造代码块、构造函数同时存在时的执行顺序:静态代码块 à 构造代码块 à 构造函数;
生成Java帮助文档:命令格式:javadoc –d 文件夹名 –auther –version *.java
/** //格式
*类描述
*@author 做者名
*@version 版本号
*/
/**
*方法描述
*@param 参数描述
*@return 返回值描述
*/
---------------------------------------------------------------------------------------------
设计模式:解决问题最行之有效的思想。是一套被反复使用、多数人知晓的、通过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
java中有23种设计模式:
单例设计模式:★★★★★
解决的问题:保证一个类在内存中的对象惟一性。
好比:多程序读取一个配置文件时,建议配置文件封装成对象。会方便操做其中数据,又要保证多个程序读到的是同一个配置文件对象,就须要该配置文件对象在内存中是惟一的。
Runtime()方法就是单例设计模式进行设计的。
如何保证对象惟一性呢?
思想:
1,不让其余程序建立该类对象。
2,在本类中建立一个本类对象。
3,对外提供方法,让其余程序获取这个对象。
步骤:
1,由于建立对象都须要构造函数初始化,只要将本类中的构造函数私有化,其余程序就没法再建立该类对象;
2,就在类中建立一个本类的对象;
3,定义一个方法,返回该对象,让其余程序能够经过方法就获得本类对象。(做用:可控)
代码体现:
1,私有化构造函数;
2,建立私有并静态的本类对象;
3,定义公有并静态的方法,返回该对象。
---------------------------------------------
//饿汉式
class Single{
private Single(){} //私有化构造函数。
private static Single s = new Single(); //建立私有并静态的本类对象。
public static Single getInstance(){ //定义公有并静态的方法,返回该对象。
return s;
}
}
---------------------------------------------
//懒汉式:延迟加载方式。
class Single2{
private Single2(){}
private static Single2 s = null;
public static Single2 getInstance(){
if(s==null)
s = new Single2();
return s;
}
}
-------------------------------------------------------------------------------------------------
继 承(面向对象特征之一)
好处:
1:提升了代码的复用性。
2:让类与类之间产生了关系,提供了另外一个特征多态的前提。
父类的由来:实际上是由多个类不断向上抽取共性内容而来的。
java中对于继承,java只支持单继承。java虽然不直接支持多继承,可是保留了这种多继承机制,进行改良。
单继承:一个类只能有一个父类。
多继承:一个类能够有多个父类。
为何不支持多继承呢?
由于当一个类同时继承两个父类时,两个父类中有相同的功能,那么子类对象调用该功能时,运行哪个呢?由于父类中的方法中存在方法体。
可是java支持多重继承。A继承B B继承C C继承D。
多重继承的出现,就有了继承体系。体系中的顶层父类是经过不断向上抽取而来的。它里面定义的该体系最基本最共性内容的功能。
因此,一个体系要想被使用,直接查阅该系统中的父类的功能便可知道该体系的基本用法。那么想要使用一个体系时,须要创建对象。建议创建最子类对象,由于最子类不只可使用父类中的功能。还可使用子类特有的一些功能。
简单说:对于一个继承体系的使用,查阅顶层父类中的内容,建立最底层子类的对象。
子父类出现后,类中的成员都有了哪些特色:
1:成员变量。
当子父类中出现同样的属性时,子类类型的对象,调用该属性,值是子类的属性值。
若是想要调用父类中的属性值,须要使用一个关键字:super
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:覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)
继承的一个弊端:打破了封装性。对于一些类,或者类中功能,是须要被继承,或者复写的。
这时如何解决问题呢?介绍一个关键字,final:最终。
final特色:
1:这个关键字是一个修饰符,能够修饰类,方法,变量。
2:被final修饰的类是一个最终类,不能够被继承。
3:被final修饰的方法是一个最终方法,不能够被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
其实这样的缘由的就是给一些固定的数据起个阅读性较强的名称。
不加final修饰不是也可使用吗?那么这个值是一个变量,是能够更改的。加了final,程序更为严谨。常量名称定义时,有规范,全部字母都大写,若是由多个单词组成,中间用 _ 链接。
抽象类: abstract
抽象:不具体,看不明白。抽象类表象体现。
在不断抽取过程当中,将共性内容中的方法声明抽取,可是方法不同,没有抽取,这时抽取到的方法,并不具体,须要被指定关键字abstract所标示,声明为抽象方法。
抽象方法所在类必定要标示为抽象类,也就是说该类须要被abstract关键字所修饰。
抽象类的特色:
1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(能够描述类和方法,不能够描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不能够被建立对象(实例化)。
4:只有经过子类继承抽象类并覆盖了抽象类中的全部抽象方法后,该子类才能够实例化。不然,该子类仍是一个抽象类。
抽象类的细节:
1:抽象类中是否有构造函数?有,用于给子类对象进行初始化。
2:抽象类中是否能够定义非抽象方法?
能够。其实,抽象类和通常类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。因此抽象类和通常类在定义上,都是须要定义属性和行为的。只不过,比通常类多了一个抽象函数。并且比通常类少了一个建立对象的部分。
3:抽象关键字abstract和哪些不能够共存?final , private , static
4:抽象类中可不能够不定义抽象方法?能够。抽象方法目的仅仅为了避免让该类建立对象。
-----------------------------------------------------------------------------------------------
模板方法设计模式:
解决的问题:当功能内部一部分实现时肯定,一部分实现是不肯定的。这时能够把不肯定的部分暴露出去,让子类去实现。
abstract class GetTime{
public final void getTime(){ //此功能若是不须要复写,可加final限定
long start = System.currentTimeMillis();
code(); //不肯定的功能部分,提取出来,经过抽象方法实现
long end = System.currentTimeMillis();
System.out.println("毫秒是:"+(end-start));
}
public abstract void code(); //抽象不肯定的功能,让子类复写实现
}
class SubDemo extends GetTime{
public void code(){ //子类复写功能方法
for(int y=0; y<1000; y++){
System.out.println("y");
}
}
}
this:表明当前对象,也就是所在函数所属对象的引用。
this对象后面加.调用的是对象的成员变量和方法。(this.say());
this对象后面加(),调用的是本类中对应参数的构造函数。
super:表明父类,也就是当前类的父类。
使用方式与this相似。
构造函数:用于当对对象初始化时调用的特殊函数,只在执行一次。
在构造函数中使用this或者super,必须定义在构造函数的第一行。若是没有用到,那么构造函数的第一句会默认的加上super();
构造代码块:是给全部的对象进行初始化,也就是,全部的对象都会调用的一个代码块,只要对象一建,就会调用这个代码块,用于给不一样对象的共性初始化,优先于构造函数执行。
格式:{
代码。。。。。。
}
静态代码块:一个用static关键字标示的一个代码块区域,定义在类中。能够完成类的初始化,静态代码块会随着类的加载而执行一次(new多个对象也是只执行一次)。若是和主函数在同一个类中,优先于主函数执行。
格式:static{
代码。。。。。
}
三种初始化的执行顺序: 静态代码块--->构造代码块------>构造函数。
重写:覆盖父类已有的方法,子父类方法必须如出一辙。(包括返回值,子类复写父类方法时访问权限必须比父类大或者同级。方法要么都静态,要么都不静态)。
重载:只在本类中的多个方法,只看同名函数的参数列表。
子类初始化时,先初始化父类的方法和变量,在初始化本身的。
接口能够被多实现,类继承只能单继承。
接口与接口之间存在着继承关系,接口能够多继承接口。
成员变量:
编译时期:参考的引用类型变量所属的类中是否有调用的成员。(编译时期不产生对象,只检查语法错误)。
运行时期:也是参考引用类型变量所属的类中是否有调用的成员。
简单总结:成员变量——编译运行都看 = 左边。
非静态成员函数:
编译时期:参考引用类型变量所属的类中是否有调用的方法。
运行时期:参考的是对象所属的类中是否有调用的方法。
缘由:由于在子父类的非晶态成员函数中有一个特性:重写(覆盖)。
简单总结:成员函数——编译看 = 左边, 运行看 = 右边。
静态函数:
编译时期:参考引用类型变量所属的类中是否有调用的方法。
运行时期:参考的是引用类型所属的类中是否有调用的方法。
缘由:由于是静态方法,因此是不属于对象的,而是属于该方法所在的类。
简单总结:成员函数——编译运行看 = 左边,
特色:内部类能够直接访问外部类中的成员,而外部类想要访问内部类,必需要创建内部类的对象。
-------------------------------------------------------------------------------------------------------------------------------
class Outer{
int num = 4;
class Inner {
void show(){
System.out.println("inner show run" + num);
}
}
public void method(){
Inner in = new Inner();//建立内部类的对象
in.show();//调用内部类的方法
}
-------------------------------------------------------------------------------------------------------------------------------
直接访问内部类格式:外部类名.内部类名 变量名 = new 外部类对象.内部类对象;
Outer.Inner in = new Quter.new Inner();
上面这种方式比较少见,由于内部类原本就是为了封装,想要获取内部类对象一般都是经过外部类的方法来获取,这样能够对内部类对象进行控制。
一般内部类被封装,都会被私有化。
若是内部类被静态修饰,至关于外部类,会出现访问局限性,只能访问外部类中的静态成员。
外部其余类中,直接访问static内部类的非静态成员:New Outer.Inner().show();
外部其余类中,直接访问static内部类的静态成员:Outer.Inner.show();
通常内部类通过编译后文件名为:“外部类名$内部类名.class”;
1.不能够被成员修饰符修饰(例如:static,static是修饰成员的)
2.能够访问外部类中成员,由于还持有外部类中的引用,(外部内.this),但不能够访问它所在的局部中的变量,只能访问被final修饰的局部变量。
匿名内部类的格式:new 父类名&接口名(){定义子类成员或者覆盖父类方法}.方法
case:
new Object(){
void show(){
System.out.prinlt("show run");
}
} .show();
1.使用throws来在方法上标识(声明),方法可能会出现异常,当调用者检查到有标识时有必需要进行处理,要么接着抛,要么try。不然会出现编译失败
声明格式:throws 异常类,异常类。。。。。并非全部的异常都须要声明,RuntimeException(运行时异常)类及其子类能够不用声明。
2.捕获异常try{}catch(){}块来捕捉时,要注意有多个catch时,若是有父类的Exception语句块,必定要放在下面.
3.throw用于抛出异常对象。
1.当子类覆盖父类的方法时,若是父类的方法抛出了异常,那么子类的方法要么不抛出异常,要么就抛出父类异常或者该异常的子类,不能抛出其余异常。若是父类没有抛出异常,那么子类只能try不能throws.
2.若是父类抛出了多个异常,那么子类在覆盖时只能抛出父类异常的子集。
3.若是这个异常子类没法处理,已经影响了子类方法的具体运算,这时能够在子类方法中,经过throw抛出RuntimeException异常或者其子类,这样,子类方法就不须要throws进行声明。
进程:正在进行中的程序,就是一个应用程序运行时的内存分配空间
线程:进程中一个程序的执行控制单元,一条执行路径。
进程负责的是应用程序的空间的标示,线程负责的是应用程序的执行顺序。
cpu随机性原理:由于cpu的快速切换形成,那个线程获取到了CPU的执行权,那个线程就执行。
被建立:start()。
运行:具有执行资格,同时具有执行权。
冻结:sleep(time),wait()-----notify()唤醒,线程冻结(沉睡),释放了执行权,同时释放了执行资格。
临时阻塞状态:线程具有cpu的执行资格,没有cpu的执行权。
消亡:stop();
第一种方式:继承Thread,由子类复写run方法。
步骤:1.定义类继承Thread类。
2.目的是复写run方法,将要让线程运行的代码都存储到run方法中。
3.经过建立Thread类的子类对象,建立线程对象。
4.调用线程的start方法,开启线程,并执行run方法。
第二种方式:实现一个Runable接口。
步骤:1.定义类实现Runnable接口。
2.覆盖接口中的run方法。(用于封装线程要运行的代码)。
3.经过Thread类建立线程对象。
4.将实现了Runnable接口的子类做为实际参数传递给Thread类中的构造函数。(为何要这么作?是为了让线程对象明确要运行的run方法所属的对象)。
5.调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
通常状况推荐使用第二种方式,能够避免单继承。
经过图能够发现一个线程在执行多条语句时,并运算同一个数据时,在执行过程当中,其余线程参与进来,并操做了这个数据,那么会致使错误数据产生。
产生的两个因素:1.多条线程在操做共享数据。2.有多条语句对共享数据进行运算。
缘由:这多条语句,在某一个时刻被一个线程执行是,还没执行完,cpu时间片到了,被其余线程执行了。
为了解决上面所说的线程安全问题而产生的技术,解决的思路就是:加同步,加锁,将要操做共享数据的语句在某一时段让一个线程执行完,在线程执行过程当中,其余线程不能进来执行。
格式:
synchronized (对象){ //任意对象均可以,这个对象就是锁
//须要被同步的代码
}
定义同步的前提:
1.必需要有两个或者两个以上的线程,才须要同步。
2.多个线程必须保证使用的是同一个锁。
1.同步函数所使用的锁是this对象。
2.当同步函数被static修饰时,因为此时的函数是属于类的,这时可能尚未产生该类的对象,可是该类的字节码文件加载进了内存就已经被封装成了对象,因此此时的锁就是字节码文件对象,也就是类名.class对象。
同步代码块使用的锁能够是任意对象。
同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象。
避免死锁:线程通讯→等待唤醒机制,涉及的方法:
wait:将同步中的线程处理为冻结状态。释放了执行权,释放了资格。同时将线程对象存储到线程池中。
notify:唤醒线程池中某一个线程。
notifyAll:唤醒线程池中全部的线程。
注意:1.这些方法都须要定义在同步中。2.由于这些方法都必需要标示所属的锁。由于A锁上的wait只能,让A锁去唤醒notify。(A.wait()----->A.notify)。
wait和sleep区别:分析这两个方法。从执行权和锁角度来分析。
wait:能够指定时间,也能够不指定时间,若是不指定时间,只能由对应的notify或者notifyAll来唤醒。 线程会释放执行权,并且线程也会释放锁。
sleep:必须指定时间,时间到线程自动由冻结状态转为运行状态(或者临时阻塞状态)。 线程会释放执行权,可是不会释放锁。
字符串特色:字符串一旦被初始化,就不能够改变,存放在方法区的常量池中。只要出现了“ ”(双引号)的数据那么就是字符串对象。关于
这里简单说一下关于Java的内存分布:1:寄存器 2:本地方法区 (静态方法,常量)3:方法区 4:栈(局部变量) 5:堆(实体,就是对象和数组)。
2.字符容器:StringBuffer 和 StringBuilder。
StringBuffer特色:1.初始容量为16个字符。
2.能够对字符串内容进行修改。
3.可变长度。
4.缓存区中能够存储任意类型的数据。
5.最终须要变成字符串。
6.最重要的线程安全的。
StringBuilder:与buffer如出一辙,只是它是线程不安全的。
总结:多线程操做,使用StringBuffer安全。单线程使用StringBuilder效率高。
特色:
1.对象封装数据,对象多了也须要存储。集合用于存储对象。
2.对象的个数肯定可使用数组,但不肯定个数怎么办,可使用集合,由于集合时可变长度
集合与数组的区别:
1.数组是固定长度:集合可变长度的。
2.数组能够存储基本数据类型,也能够存储引用数据类型。集合只能存储引用数据类型。
3.数组存储的元素必须是同一个数据类型;集合存储的对象能够是不一样数据类型。
Collection:
|--List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素能够重复。
|--Set:无序(存入和取出顺序有可能不一致),不能够存储重复元素。必须保证元素惟一性。
迭代器:是一个接口。做用:用于取集合中的元素。
boolean |
hasNext() 若是仍有元素能够迭代,则返回 true。 |
next() 返回迭代的下一个元素。 |
|
void |
remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操做)。 |
每个集合都有本身的数据结构,都有特定的取出本身内部元素的方式。为了便于操做全部的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。
也就说,只要经过该接口就能够取出Collection集合中的元素,至于每个具体的容器依据本身的数据结构,如何实现的具体取出细节,这个不用关心,这样就下降了取出元素和具体集合的耦合性。
List自己是Collection接口的子接口,具有了Collection的全部方法。如今学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特色。
List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素能够重复。
|--ArrayList:底层的数据结构是数组,线程不一样步,ArrayList替代了Vector,查询元素的速度很是快。
|--LinkedList:底层的数据结构是链表,线程不一样步,增删元素的速度很是快。
|--Vector:底层的数据结构就是数组,线程同步的,Vector不管查询和增删都巨慢。
对于List的遍历,不只可使用Iterator接口,也可使用下表(索引)来遍历,list.get(index);
Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。
|--HashSet:底层数据结构是哈希表,线程是不一样步的。无序,高效;
HashSet集合保证元素惟一性:经过元素的hashCode方法,和equals方法完成的。
当元素的hashCode值相同时,才继续判断元素的equals是否为true。
若是为true,那么视为相同元素,不存。若是为false,那么存储。
若是hashCode值不一样,那么不判断equals,从而提升对象比较的速度。
|--LinkedHashSet:有序,hashset的子类。
|--TreeSet:对Set集合中的元素的进行指定顺序的排序。不一样步。TreeSet底层的数据结构就是二叉树。
哈希表的原理:
1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。
2,哈希值就是这个元素的位置。
3,若是哈希值出现冲突,再次判断这个关键字对应的对象是否相同。若是对象相同,就不存储,由于元素重复。若是对象不一样,就存储,在原来对象的哈希值基础 +1顺延。
4,存储哈希值的结构,咱们称为哈希表。
5,既然哈希表是根据哈希值存储的,为了提升效率,最好保证对象的关键字是惟一的。
这样能够尽可能少的判断关键字对应的对象是否相同,提升了哈希表的操做效率。
6.在HashSet中尽可能不要改变参与运算hashCode值的变量,以防止内存泄露。。
对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。
用于对Set集合进行元素的指定顺序排序,排序须要依据元素自身具有的比较性。
若是元素不具有比较性,在运行时会发生ClassCastException异常。
因此须要元素实现Comparable接口,强制让元素具有比较性,复写compareTo方法。
依据compareTo方法的返回值,肯定元素在TreeSet数据结构中的位置。
TreeSet方法保证元素惟一性的方式:就是参考比较方法的结果是否为0,若是return 0,视为两个对象重复,不存。
注意:在进行比较时,若是判断元素不惟一,好比,同姓名,同年龄,才视为同一我的。
在判断时,须要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。
TreeSet集合排序有两种方式,Comparable和Comparator区别:
1:让元素自身具有比较性,须要元素对象实现Comparable接口,覆盖compareTo方法。
2:让集合自身具有比较性,须要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象做为实际参数传递给TreeSet集合的构造函数。
第二种方式较为灵活。
|--Hashtable:底层是哈希表数据结构,是线程同步的。不能够存储null键,null值。
|--HashMap:底层是哈希表数据结构,是线程不一样步的。能够存储null键,null值。替代了Hashtable.
|--TreeMap:底层是二叉树结构,能够对map集合中的键进行指定顺序的排序。
Map集合存储和Collection有着很大不一样:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。
特色:要保证map集合中键的惟一性。
想要获取map中的全部元素:
原理:map中是没有迭代器的,collection具有迭代器,只要将map集合转成Set集合,可使用迭代器了。之因此转成set,是由于map集合具有着键的惟一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
★ 把map集合转成set的方法:
Set keySet();
Set entrySet();//取的是键和值的映射关系。
Entry就是Map接口中的内部接口;
为何要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map中的键值对。
---------------------------------------------------------
取出map集合中全部元素的方式一:keySet()方法。
能够将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再经过get方法对获取到的键进行值的获取。
Set keySet = map.keySet();
Iterator it = keySet.iterator();
while(it.hasNext()) {
Object key = it.next();
Object value = map.get(key);
System.out.println(key+":"+value);
}
-------------------------------------------------------
取出map集合中全部元素的方式二:entrySet()方法。
Set entrySet = map.entrySet();
Iterator it = entrySet.iterator();
while(it.hasNext()) {
Map.Entry me = (Map.Entry)it.next();
System.out.println(me.getKey()+"::::"+me.getValue());
}
--------------------------------------------------------
使用集合的技巧:
看到Array就是数组结构,有角标,查询速度很快。
看到link就是链表结构:增删速度快,并且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
看到hash就是哈希表,就要想要哈希值,就要想到惟一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
看到tree就是二叉树,就要想到排序,就想要用到比较。
比较的两种方式:
一个是Comparable:覆盖compareTo方法;
一个是Comparator:覆盖compare方法。
LinkedHashSet,LinkedHashMap:这两个集合能够保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
集合何时用?
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。
保证惟一,就用Set。不保证惟一,就用List。
Collections:它的出现给集合操做提供了更多的功能。这个类不须要建立对象,内部提供的都是静态方法。
Collection 和 Collections的区别:
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操做。
Collection是个java.util下的接口,它是各类集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操做,如插入、删除、判断一个元素是否其成员、遍历等。
Arrays:
用于操做数组对象的工具类,里面都是静态方法。
关于集合内部的方法,这里就不介绍了,API中都有。
1.流:能够理解为数据的流动,就是数据流。IO流最终要以对象来体现,对象都存在IO包中。流的操做只要两种,读和写。
2.流也能够进行分类:1.输入流(读)和输出流(写)。2.由于处理的的数据不一样,分为字符流(Reader Writer)和字节流(InputStream OutputStream)。
字节流:处理字节数据的流对象。计算机底层的数据都是二进制格式字节,因此字节流的数据能够是音频,图片,文字等计算机中能够储存的数据。
字符流:为何要有字符流?字节流不是能够操做一切数据?由于字符每一个国家都不同,因此涉及到了字符编码问题,像若是咱们的使用GBK的编码,却按照ISO8859-1去解码是有问题的,因此须要咱们在获取文字字节数据的同时+制定的编码表才能够正确解析数据。于是将字节流和编码表封装为对象,就是字符流,只要操做字符数据,那么清闲考虑使用字符流体系。
1.close()方法和flush()的区别:
flush():将缓存区的数据刷到目的地中后,流能够继续使用。
close():将缓冲区数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源,这个动做在使用完毕流后必定要作。
2.FileWriter写入数据的细节:
windows中的换行符:\r\n 两个符号组成。 linux:\n。
在原数据上续写数据,只要在new 流对象的构造函数中传入新的参数true。
目录分割符: windows \\ /。
流的两种读取数据方法:1.不带缓冲区,每次读取一个(fr.read())。2.自定义缓冲区(fr.read(buff))
case 1:核心代码
[java] view plain copy
case 2:
[java] view plain copy
字符流:
Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。
|---BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 能够指定缓冲区的大小,或者可以使用默认的大小。大多数状况下,默认值就足够大了。
|---LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
|---InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集能够由名称指定或显式给定,或者能够接受平台默认的字符集。
|---FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要本身指定这些值,能够先在 FileInputStream 上构造一个 InputStreamReader。
|---CharArrayReader:
|---StringReader:
-------------------------------------------------
Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
|---BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
|---OutputStreamWriter:是字符流通向字节流的桥梁:可以使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集能够由名称指定或显式给定,不然将接受平台默认的字符集。
|---FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要本身指定这些值,能够先在 FileOutputStream 上构造一个 OutputStreamWriter。
|---PrintWriter:
|---CharArrayWriter:
|---StringWriter:
---------------------------------
字节流:
InputStream:是表示字节输入流的全部类的超类。
|--- FileInputStream:从文件系统中的某个文件中得到输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
|--- FilterInputStream:包含其余一些输入流,它将这些流用做其基本数据源,它能够直接传输数据或提供一些额外的功能。
|--- BufferedInputStream:该类实现缓冲的输入流。
|--- ObjectInputStream:
|--- PipedInputStream:
-----------------------------------------------
OutputStream:此抽象类是表示输出字节流的全部类的超类。
|--- FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
|--- FilterOutputStream:此类是过滤输出流的全部类的超类。
|--- BufferedOutputStream:该类实现缓冲的输出流。
|--- PrintStream:
|--- DataOutputStream:
|--- ObjectOutputStream:
|--- PipedOutputStream:
--------------------------------
缓冲区是提升效率用的,给谁提升呢?
BufferedWriter:是给字符输出流提升效率用的,那就意味着,缓冲区对象创建时,必需要先有流对象。明确要提升具体的流对象的效率。
[java] view plain copy
-----------------------------
BufferedReader:
[java] view plain copy
流对象:其实很简单,就是读取和写入。可是由于功能的不一样,流的体系中提供N多的对象。那么开始时,到底该用哪一个对象更为合适呢?这就须要明确流的操做规律。
流的操做规律:
1,明确源和目的。
数据源:就是须要读取,可使用两个体系:InputStream、Reader;
数据汇:就是须要写入,可使用两个体系:OutputStream、Writer;
2,操做的数据是不是纯文本数据?
若是是:数据源:Reader
数据汇:Writer
若是不是:数据源:InputStream
数据汇:OutputStream
3,虽然肯定了一个体系,可是该体系中有太多的对象,到底用哪一个呢?
明确操做的数据设备。
数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。
4,须要在基本操做上附加其余功能吗?好比缓冲。
若是须要就进行装饰。
转换流特有功能:转换流能够将字节转成字符,缘由在于,将获取到的字节经过查编码表获取到指定对应字符。
转换流的最强功能就是基于 字节流 + 编码表 。没有转换,没有字符流。
发现转换流有一个子类就是操做文件的字符流对象:
InputStreamReader
|--FileReader
OutputStreamWriter
|--FileWrier
想要操做文本文件,必需要进行编码转换,而编码转换动做转换流都完成了。因此操做文件的流对象只要继承自转换流就能够读取一个字符了。
可是子类有一个局限性,就是子类中使用的编码是固定的,是本机默认的编码表,对于简体中文版的系统默认码表是GBK。
FileReader fr = new FileReader("a.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");
以上两句代码功能一致,
若是仅仅使用平台默认码表,就使用FileReader fr = new FileReader("a.txt"); //由于简化。
若是须要制定码表,必须用转换流。
转换流 = 字节流+编码表。
转换流的子类File = 字节流 + 默认编码表。
转换流使用格式:转换流 fr = new 转换流(包装的流,指定的编码集);
InputStreamReader fr = new InputStreamReaderfr (new FileInputStream("a.txt"),"GBK")
1.逻辑端口:用于表示进程的逻辑地址,不一样的进程的标识;有效进程:0~65535,其中0~1024是系统使用或者保留端口
2.物理端口:指的是主机或者其余设备上提供的外接接口。
Java中的IP对象 InetAddress.
Socket套接字,通讯的端点:就是为网络服务提供的一种机制,通讯两端都有Socket,网络通讯其实就是端口Socket间的通讯,数据在两个Socket之间经过IO传输
1.UDP:面向数据包的传输,是面向无链接的方式.
UDP传输:
1.只要进行网络传输,必须须要Socket套接字。
2.数据必定要封装到数据包中,数据包中包含IP地址,端口号,数据等信息。
Java中封装操做UDP来进行网络通讯的主要类是DatagramSocket对象以及DatagramPacket(数据包)。
DatagramSocket:具有接受和发送功能,但进行传输时,须要明确发送端和接收端。
DatagramPacket:数据包对象,用于操做数据包中的各类信息。
UDP传输发送端的步骤:
1.创建UDP的Socket服务,建立对象时若是没有声明端口,那么系统会自动分配给其一个未使用的端口号。
2.明确要发送的数据。
3.将数据封装到数据包对象中。
4.用Socket的Send方法将数据包发送出去。
5.关闭资源(必须记得作)
下面给出一个例子做为参考:
[java] view plain copy
UDP传输接受端的步骤:
1.创建UDP的Socket服务,明确一个端口,做用在于,只有发送到这个端口的数据才是这个接受端能够接受处理的数据
2.建立数据包对象用于接受(存储)数据包。
3.利用Socket服务的接受方法将收到的数据存储到数据包中。
4.经过数据包对象获取数据包中的具体内容,如ip地址,端口,数据等。
5.关闭资源(必须作)
接受端的例子:
[java] view plain copy
TCP传输:两个端点创建链接后会有一个传输数据的通道,这通道成为流,并且是创建在网络基础之上的流,称之为Socket流,该流中既有读取,也有写入。
相关概念:TCP中的两个端点须要严格区分:一个是服务端,一个是客户端。
客户端:对应的对象,Socket
服务端:对应的对象,ServerSocket
TCP客户端:
1.创建TCPde Socket服务,最好明确具体的地址和端口,这个对象在建立时,就已经能够对指定ip和端口进行链接(三次握手)。
2.若是链接成功,就意味通道创建了,Socket流已经产生了。只要获取到Socket流中的读取流和写入流便可,只要通getInputStream和getOutputStream就能够获取到两个流对象。
3关闭资源。
case 1 :
[java] view plain copy
TCP服务端:
1.建立Socket服务,并监听一个指定的端口。
2.服务端为了客户端提供服务,获取客户端的内容,能够经过accept方法获取链接过来的客户端对象。
3.能够经过获取到的Socket对象中的Socket流和具体的客户端进行通信。
4.若是通信结束,关闭资源。注意:要先关客户端,再关服务端。
case 2:
[java] view plain copy
网络编程中的URLEncoder和URLDecoder.
URLEncoder类的encode()静态方法:是将一个普通的字符串转化为一个百分号编码格式字符串。
URLDecoder类的decode()静态方法:是将百分号编码格式字符串转化为一个普通的字符串。
URL与URLConnection对象:前者是表示应用程序和URL之间的通讯链接,后者表示与URL之间的HTTP链接。程序能够经过URLConnection实例向该URL发生请求,读取URL引用的资源。
未完待续。。。。。持续更新