- Linux基本知识
- Linux目录结构
- 相对路径和绝对路径
相对路径:文件或目录相对于当前工作目录的位置
绝对路径:文件或目录相对于根目录的位置
相对路径:
.表示当前目录
..表示上一级目录
绝对路径:
/home/soft01
- pwd 显示当前的工作目录
- Java编译运行环境
编写的java源文件(.java)首先经过编译,生成字节码文件(.class)。
JVM为字节码文件提供运行环境(标准的.class文件,可以在不同的JVM上运行,一次编译,处处运行)。 - JDK、JRE、JVM
JDK(Java Development Kit):Java开发工具包
JRE(Java Runtime Encironment) :Java运行环境
JVM:Java虚拟机
运行一个java程序所需的最小环境为JRE,开发一个java程序需要最小的环境为JDK - Java基本数据类型
byte,short,char,int、long,double,boolean,float - 重写和重载的区别:
重载:
在类内,相同的方法的名称,但参数的个数和类型不相同
重写:
跨类且继承,子类把长辈的方法体覆盖 - equals跟==的区别:
- ==是一个判断相等的运算符
这个运算符的两边如果是基本数据类型,判断的是基本数据类型的值是否相等。 这个运算符的两边如果是某个类类型的对象,判断的是两个对象是否是同一个地址,如果地址相同,那么内容就一定相同,如果地址不相同,内容就不一定相同。 - equals方法不能判断基本数据类型的数据,只能判断对象是否相等。如果没有重写equals方法,那么equals方法判断的是地址。
- synchornized
synchornized同步,asynchronized 异步
同步资源,同步锁
- 此关键字修饰在方法上
比如:
public synchornized void method1(){
//代码块
}
当线程1调用method1方法的时候,
线程2,必须等待线程1调用完method1方法,
后才能调用method1方法
- 此关键字修饰在对象上 ,同步块
比如:
synchornized(某个对象){
代码块
}
当线程1访问同步块的时候,
线程2,必须等待线程1调用完同步块,
后才能调用同步块
- 此关键字修饰在类上, 同步块
比如:
synchornized(类名.class){
代码块
}
当线程1访问同步块的时候,
线程2,必须等待线程1调用完同步块,
后才能调用同步块
用户写线程有两种方式:
方式一:
用户自己写线程开发
Runnable r=new Runnable(){重写run方法}//写线程的逻辑
Thread t1=new Thread(r);
Thread t2=new Thread(r);
...
线程对象.start();
方式二:
java给程序员提供一个线程池的概念
线程池:
就是把若干用户线程添加到线程池中,由线程池来统一管理线程
为什么要使用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复
使用,或利用,可以并发执行多个任务
2.可以根据系统的承受能力,调整线程池中的工作线程数目
防止因为消耗过多的内存,而是服务器宕机(down)
结论:就是java给提供一批api方法,用于更好的管理线程
程序员只需要专注于写run方法(线程的逻辑)
线程池的使用:
有一个Executors的线程工具类,此类提供了若干静态方法
这些静态方法用于生成线程池的对象
1.Executors.newSingleThreadExecutor();
创建一个单线程的线程池,这个线程池只有一个线程在工作
即单线程执行任务,如果这个唯一的线程因为异常结束,
那么就会有一个新的线程来替代它,,因此线程池保证所有的
任务是按照任务的提交顺序来执行
2.Executors.newFixedThreadPool();
创建固定大小的线程池,每次提交一个任务就创建一个线程
直到线程达到线程池的最大的大小,线程池的大小一旦达到
最大就会保持不变,如果某个线程因为执行异常而结束,
那么久会补充一个新的线程
3.Executors.newCachedThreadPool();
创建了一个可以缓冲的线程池,如果线程大小超过处理任务
所需要的线程,那么就回收部分线程,当线程数增加的时候
此线程池由可以智能添加新的线程来处理任务
此线程不会对线程池大小做限制,线程池的大小完全依赖
操作系统能够创建的最大大小
4.Executors.newScheduledThreadPool()
创建一个大小无限制的线程池,此线程池支持定时以及
周期性的执行任务的需求
- 网络编程:
分类:
- tcp编程(重点):tcp 传输控制协议,能够保证在数据传递时,数据不丢失。
tcp/ip:传输控制/网络协议
传输控制协议用户传输数据
网络协议用户定位源和目标
数据在传输的过程中,如果数据丢失,会重传,
目标正确接收完毕 - udp编程(略掉):不保证数据能够传输到目标
若干名词:
-socket:套接字
-ip地址
ipv4 4段地址
ipv6 6段地址
用于唯一确定网络上的计算机
-端口号:
每台计算机都有65535个端口 0-65535
能够访问计算的"门"
特殊的端口:
80端口:http协议的默认端口 超文本传输协议
21端口:ftp协议的默认端口 文件传输协议
25端口:smtp协议的默认端口 邮件传输协议
-tcp/ip:传输控制协议/网络协议
socket套接字:
用于描述ip地址和端口号,是一个通讯链的句柄(java中引用)
在internet上的一个主机,一般运行多少个服务的软件,同时
就提供多少个服务,每个服务监听一个端口,不同端口对应
不同的服务
最终应用程序和服务器通过socket套接字建立网络连接
发送请求和接收请求
服务端套接字
ServerSocket类
Socket accept();
用于监听,并接收到套接字的连接
void close();
关闭Socket
InetAddress getInetAddress();
返回此服务器套接字的本地地址
int getLocalPort()
返回此套接字在其上的监听的端口号
客户端套接字
Socket类:
Socket(String host,int port);
创建一个套接字,并将其连接到指定ip地址,和这个
IP地址对应的端口号
void close()
关闭socket
InetAddress getInetAddress();
返回此服务器套接字的本地地址
int getLocalPort()
返回此套接字在其上的监听的端口号
jdk1.5的新特性(重点):
自动装箱和拆箱:
装箱:把基本数据类型的数据装箱成对象类型
拆箱:把对象的类型变成基本数据类型
在jdk1.5及以后版本自动装箱和拆箱
int i=10;
Integer ii=i;
int k=ii
在jdk1.5以前的版本
int i=10;
Integer ii=new Integer(10);
int k=ii.intValue();
- 反射的api:
- 反射的方式创建对象
1.用无参数构造创建对象
Class对象.newInstance();//常用的做法
2.用有参数构造创建对象
Class对象.getConstructor(new Class[]{若干参数的类类型})
.newInstance(构造函数的参数);
比如:
//有参数构造
public User(String name,String password){
}
Class clazz=User.class;
//传统的实例化对象
User user=new User("zhangsan","zs");
//反射的做法:
User user=clazz.getConstructor(new Class[]{String.class,String.class})
.newInstance("张三","zs");
- 反射方式获取Field中的信息
1.获取当前类以及长辈类的public Field
Field[] fields=Class对象.getFields();
2.获取当前类中的所有的属性Field
Field[] fields=Class对象.getDeclaredFields()
3.获取当前类以及长辈类中指定的共有属性
Field field=Class对象.getField(String fieldName);
4.获取当前类中指定的属性
Field field=Class对象.getDeclaredField(String fieldName);
5.通过反射设定Field属性
Field对象.set(Object obj,Object value);
如果Field是私有的
必须先执行:Field对象.setAccessable(true);//设置属性可以访问
6.通过反射获取Field的值
Object value=Field对象.get(object);
如果Field是私有的
必须先执行:Field对象.setAccessable(true);//设置属性可以访问
- 反射方式获取Method方法信息
1.获取当前类以及长辈类的public Method
Method[] methods=Class对象.getMethods();
2.获取当前类中的所有的属性Field
Method[] methods=Class对象.getDeclaredMethods()
3.获取当前类以及长辈类中指定的共有属性
Method method=Class对象.getMethod(String methodName,new Class[]{方法参数类型});
4.获取当前类中指定的属性
Method method=Class对象.getDeclaredMethod(String methodName,new Class[]{方法参数类型});
5.通过反射动态调用Method
Object returnValue =Method对象.invoke(Object obj,object...args);
解析:
就是通过obj这个对象,调用Method对象确定的方法,给这个方法传递的参数是args
Method对象对应的方法放回值returnValue;
-反射获取Constructor构造函数
-具体查看api文档
-反射获取注解Annotation
-具体查看api文档
在哪些地方使用反射,反射的应用场景
-用反射实现jdbc的通用查询和通用更新
-用反射解析注解
-单元测设,就是用反射实现的
-常见的框架,spring框架,springmvc框架等,都是用反射实现的
-EL表达式
等...
反射的优点:
大幅度提高开发效率,框架就是反射实现的,框架可以大大提高开发效率
反射的缺点:
反射执行效率比非反射的方式执行效率低
反射可以暴露类中的所有细节,突破了封装.
- 注解:
注解可以提高开发效率,但是执行效率堪忧,因为其底层解析
注解是用反射解析的
用注解可以替换xml配置和属性文件
注解是一个标识,注解所代表的功能一定要用反射来实现
这些反射的代码,用于解析(寻找注解,获取注解的属性值)
然后根据设定的属性值,来决定是否执行一些业务功能
使用注解有三个步骤:
1.用户定义注解 创建注解
2.把注解应用到对应的目标上 把注解放什么地方(包,类,属性,方法,方法参数等)
3.用反射的代码来确定是否有注解和注解属性值,
根据是否有注解以及注解的值做相应的功能
如何定义注解:
//程序员创建注解
//设定MyAnnotation注应用在什么位置上
@Target(value={ElementType.METHOD})
//指定注解的保留策略,source级别 class级别 runtime级别
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
//注解的value属性
public String value();
//注解的name属性,且有默认值abc
public String name() default "abc";
//注解的colors属性,且是一个数组,默认值为red和blue
public String[] colors() default {"red","blue"};
}
元注解/源注解
@Target和 @Retention和@Override等...都是jdk自带的注解
1.@Target(value={ElementType.Method,...})
指定要修饰在什么样的目标上(包,注解,类/接口,方法,属性,参数等...)
value取值是一个枚举类型的数据
ElementType:
ANNOTATION 注解
METHOD 方法
FIELD 属性
CONSTRUCTOR 构造
TYPE 类/接口
PARAMETER 方法的参数上
等...
2.@Retention(RetentionPolicy.RUNTIME)
注解的保留策略
.java--.class-->jvm执行.class
SOURCE:源代码级别,Source修饰的注解是给编译看的
编译器把源代码编译完毕后,在class文件中就没有注解
CLASSS:类级别,Class修饰的注解给类加载器看的
在类加载的时候可以做一系列的引导操作,
在编译器编译完毕后注解存在,在类加载加载之后
就要丢弃注解
RUNTIME:运行时级别,给JVM看的,在程序运行的过程中做相关的操作
可以在jvm中借助反射api解析注解
注解中的属性详解:
a.注解定义属性和接口定义的方法类似,缺省默认public
public 类型 属性名称();
b.定义属性是,如果没有使用default指定默认值
则在使用注解,必须给属性赋值
如果带有默认值,是在使用注解的时候给属性赋值为新值
也可以使用默认值
c.注解中的属性类型必须遵守如下要求
可以是八种基本数据类型,枚举类型,Class类型,String类型,
以及上面类型的一维数组
d.在给数组赋值的时候,如果数组只有一个值就不用写{}
e.有一个极特殊的属性value
如果只为该属性赋值,value=值
但是如果注解中只有value这一个属性,那么value可以省略
把注解应用到目标
在对应的目标上写上注解
@MyAnnotation(value="xx",name="yy",colors={"pink","green","gay"})
public class Demo1 {
private String str;
@MyAnnotation(value="aa",name="bb")
public void method1(String name){
}
public void method2(){
}
}
写反射代码来解析注解:
a.解析类上的注解
b.解析方法上的注解
- lambda表达式:
lambda表达式可以称之为闭包,他是java8中的一个非常重要的特性
很多java8新特性的写法都会用到lambda表达式
lambda表达式允许函数作为一个方法的参数,函数作为参数
传递到方法中,这样代码就会变得简洁
语法:
(parameters)->expression表达式
或
(parameters)->{statement代码块;}
说明:
-可选参数声明:不需要声明参数类型,编译器统一识别参数值
-可选参数圆括号:一个参数无需定义圆括号,多个参数需要定义圆括号
-可选大括号:如果主体包含了一个语句,就不需要使用大括号
-可选返回关键字:如果主体只有一个表达式返回值,则编译器
会自动返回值,大括号需要指定返回了一个数据值
比如:
//不要参数,返回值为5
()->5
//接受一个参数(推断出数字类型),返回参数的2倍
x->2*x
//接受两个参数(推断出数字类型),返回值为参数差值
(x,y)->x-y
//接受两个参数,返回值为x-y
(int x,int y)->x-y
//接受一个参数,类型为String的参数,并输出参数的值
//推断出没有返回值,相当于方法的返回值void
(String str)->System.out.println(str)
//接受两个参数(推断出数字类型,返回值为参数的差值)
(x,y)->{return (x-y);}
其实lambda表达式的本质就是接口的子实现
lambda表达式简化了匿名内部类的写法
lambda表达式另一个写法叫做函数式编程
注意:
就是把接口的实现是内部类,转换成函数式写法
使用lambda表达式需要注意变量的作用域问题:
-lambda表达式引用外层的成员变量
如果外层的成员变量为final的,则在lambda内部不能修改成员变量的值
如果外层的成员变量不是final的,则在lambda内部能修改成员变量的值
-lambda表示式的局部变量可以不用声明为final,但必须不可以被后面
的代码修改(即隐式的final特性)
-lambda表达式不允许声明一个与局部变量同名的参数或局部变量
2.方法的引用:
方法的引用方式用类名::方法名,其本质还是lambda表达式
具体的写法有四种
-构造器的引用 语法Class::new
-静态方法的引用 语法 Class::静态方法的名称
-特定类任意的对象引用 语法 Class::非静态方法名称
-特定对象的方法引用 语法 instance对象::非静态的方法的的名称
3.函数式接口
函数式接口(FunctionalInterface)就是一个有且只有一个抽象方法
但是可以有多个非抽象方法的接口
函数式接口可以用lambda表达式,也可以用方法的引用
在java8之前已经有部分的函数式接口
比如:
java.lang.Runnable
java.util.Comparator
java.io.FileFilter
等...
java1.8之后新添加的函数式接口
java.util.function 其中包含了很多的类
比如:
Consumer<T>
Predicate<T>
Supplier<T>
等...
总结:
使用函数式接口,可以用如下方式实现
1.java7的匿名内部类
2.lambda表达式
3.方法的引用
4.lambda和方法的引用都是为了提高开发效率
4.默认方法
在接口中可以放置有方法体的方法,但方法必须用default来修饰
在接口添加默认方法,是用来给所有的的子类提供一个功能
在接口中还可以放置静态的方法,但静态方法需要有方法体
5.Stream流管道
在java8中添加了一个新的抽象,称之为流Stream ,可以让程序员
以一种声明式的方式处理数据
Stream流的处理方式,可以把要处理的元素看成一种流,
流在管道种传输,并且开一在管道的节点上进行处理
处理包括:
筛选
排序
聚合
等等..
元素流在管道中经过中的操作处理,最后由最终的操作得到前面的处理结果
Stream流管道的几个名词解释
-数据源:流的源头,可以是集合,数组,IO,其他的数据源
-聚合操作:就是在流中筛选数据的操作
比如:filter,map,reduce,find,match,sorted等...
-如何生成一个Stream的流的源头
-stream() 生成一个串行流
-parallelStream() 生成一个并行流
比如:
List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
List<String> filtered=
strings.stream().filter(str->!str.isEmpty()).collect(Collectors.toList());
-用stream的forEach
forEach方法用来迭代流中的每个数据
Random random=new Random();
random.ints().limit(10).forEach(System.out::println);
-map方法用于映射每个元素对应的结果
List<Integer> numbers=Arrays.asList(3,2,3,3,7,3,5);
List<Integer>
lists=numbers.stream().map((i)->i*i).distinct().collect(Collectors.toList());
-filter方法用于通过设置条件过滤元素
List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
long count=strings.stream().filter((str)->str.isEmpty()).count();
-limit方法,用户获取指定的数量的流
Random random=new Random();
random.ints(0,100).limit(10).sorted().forEach(System.out:println);
-sorted方法用于对流进行排序
Random random=new Random();
random.ints(0,100).limit(10).sorted().forEach(System.out:println);
-Collectors 类实现了很多的归约操作
List<Integer> numbers=Arrays.asList(3,2,3,3,7,3,5);
List<Integer>
lists=numbers.stream().map((i)->i*i).distinct().collect(Collectors.toList());
List<String> strings=Arrays.asList("abc","bc","cba","qaz","qwe","");
String str=strings.stream().filter(str->!str.isEmpty()).collect(Collectors.joining(","));
6.java8的日期操作
java8通过发布新的Date-Time api(规范JSR310)来进一步加强对日期与
时间的处理
在旧版中的日期和时间api存在很多问题
-非线程安全,java.util.Date是非线程安全,所有日期类都是可变的
-设计很差,java.util.Date和java.sql.Date类都是日期类,重复定义
-时区处理很麻烦,在java.util.Date并没有提供处理时区的api
用java.util.Calendar能够控制时区
java.util.TimeZone能控制时区 java8
在java8中有一个包java.time包提供很多的新的api
-local(本地) 简化了日期和时间的处理
-zone(时区) 通过制定的时区处理日期和时间
- 项目的部署:
1.把项目打包
a.java项目打成jar包
b.web项目打成war包
c.项目的打包方式
用maven方式打包
右键单击项目--run as--maven build...--goals添入"package"
要求引入的jre是jdk中的jre
war文件或jar文件是在target目录中出现
右键单击项目--run as--maven install --会把jar或war包
打到maven本地库中
用非maven方式打包
右键单击项目--exprot--jar或war--选定路径和文件名即可
2.把war包放在tomcat目录中的webapps目录中,tomcat启动后,会
自动把war解压成一个目录
tomcat的启动方式分类:
a.利用eclipse启动
b.利用tomcat目录中/bin/启动文件或停止文件
window系统:
tomcat8w.exe windows窗口版本
或
startup.bat windows的黑白界面
shutdown.bat
linux系统:
startup.sh
shotdown.sh
c.在window系统的服务中中启动或停止tomcat服务
此时需要把tocmat的服务安装到window系统服务中
1、软件和环境
环境:JDK1.8 (确保jdk环境变量已经安装)
应用服务:Tomcat7.0(非安装版)
操作系统:Windows8
2、设置Tomcat为系统服务
win+R打开运行窗口,输入cmd打开dos窗口,
使用cd命令将位置切换到tomcat路径下的bin文件,
本机是F盘下。
先输入F:回车进入F盘,
然后输入命令cd F:\apache-tomcat-5.5.26\bin,
进入到bin文件夹。输入service命令可以查看service.bat文件
的使用说明,输入service.bat install service_name就可以
安装服务,service_name就是给服务起的名字,可以自己命名,
我这里起的名字是TomcatService。
tomcat在放在什么样的服务器中
1.tomcat项目放在自己的计算机服务器中
服务器计算机可能在本地网络中
服务器计算机在在远程的机房中
托管方式
非托管方式
2.tomcat放在远程机房中
购买不是机房的主机,购买的机房的中服务器中的一个空间
3.选择第二步骤中的一个方式启动tomcat
在浏览器中,直接访问项目即可