Java基础

发展简历

  • 1995年Sun公司发布Java语言
  • 1998年12月Sun公司发布JDK1.2,将Java分为J2SE、J2ME和J2EE三个版本,并一同发布了JSP/Servlet、EJB等规范
  • 2004年10月Sun发布JDK1.5,将JDK1.5改名为Java SE 5.0,J2EEJ2ME相应改为Java EEJava ME
  • 2009年4月20日Oracle公司收购Sun

发布周期

  • Java版本发布周期为6个月一次,每半年发布一个大版本(每个季度发布一个中间版本)

  • 3年发布一个长期支持(LTS)版本,JAVA9和JAVA10都不是长期支持版本,JAVA11是JAVA后的第一个LTS版本,Java11直到2023年都会获得技术支持及到2026都会提供补丁和安全警告.

数据类型

基本数据类型

基本数据类型转换注意点

  • 较小整数(byte或short范围内)赋值给一个byte或short,系统会自动将值转换
  • 超出int范围的值赋值给long变量时,需要显式在该数值后加lL

引用数据类型

  • 接口数组类型,好友特殊的null类型

引用数据类型转换注意点

null只能被转换成为引用类型

访问修饰符

private default protected public
同一个类中
同一个包中
子类中
全局范围内

类的继承

Java继承具有单继承的特点,每个类只有一个直接父类

方法重写

  • 遵循两同两小一大原则
    • 两同:方法名相同,形参列表相同
    • 两小:子类方法返回值类型应比父类返回值类型更小或相等,子类方法声明抛出的异常应比父类方法声明抛出的异常类更小或相等
    • 一大:子类方法的访问权限应比父类的访问权限更大或相等

泛型

  • 特点
    • 泛型化的类,可以存储所有类型的对象,但是在使用时指定了泛型的具体类型后,只能使用指定的类型
  • 声明了泛型的类,如果使用时不指定泛型类,则退化为Object类型,失去了泛型的好处
  • 好处
    • 增加一个参数化类型,获得额外类型检查型(a genetic type is a generic class or interface that is parameterized over types)
    • 增加类型安全性,避免了强制类型转换以及可能引发的类型转换错误(ClassCastException)
    • 把运行时期的问题提前到了编译期间,提升代码质量
    • 优化了程序设计,解决了黄色警告线问题,让程序更安全

例:

1
2
3
4
5
6
7
8
9
10
//泛型类
public class Student<T> {
private T stu = null;
public void addStu(T in) {
this.stu = in;
}
public T getStu() {
return this.stu;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
//测试类
public class Test {
public static void main(String[] args) {
Student<String> stu1 = new Student<>();
stu1.addStu("姜慢慢");
System.out.println(stu1.getStu());

Student<Integer> stu2 = new Student<>();
stu2.addStu(800);
System.out.println(stu2.getStu());
}
}

使用场景

  • 类、接口、方法(public <T> String Test(T t,Class<T> in))
  • 可以多个
  • 命名任意 单个 T E K V
  • 泛型继承与实现
    • 为泛型指定具体的类型,子类无须是泛型类
    • 保留泛型,子类需要声明为泛型类

边界

  • 声明类型时,可以通过extends关键字指定泛型的上边界

    • public class BoundedContainer<T extends 边界类型>
  • 使用时

    • 通过 ? extends 边界类型 指定上边界,类型是边界类型或者其子类

    • 通过 ? super 边界类型 指定下边界,传入的内容必须是边界类型的父类

    • 引申出来 List List 是不是同一种类型?不是!

    • List与List不是同一种类型

    • 如果需要支持任意内容类型,则需要使用 ? 通配符 List<?> 等价于List<? extends Object>

    • 把泛型类随着参数类型的类型变化的特性称为 类型协变

    • 例:

      1
      2
      3
      4
      public static void add(List<? extends Number> data) {}
      public static void sum(List<? super Integer> data) {}
      public static void doSth(List<Integer> ints) {}
      public static void doSth2(List<? extends Object> obj) {}
    • 泛型的实现

      • 泛型擦除 由编译器实现,无边界则将泛型擦除为Object,有边界将泛型擦除为边界类型;在使用时,增加类型的强制转换

        1
        2
        3
        4
        5
        6
        System.arraycopy(src,srcPos,dest,destPos,length)
        //src 源数组
        //srcPos 源数组起始位置
        //dest 目标数组
        //dest 目标数组的起始位置
        //length 拷贝的长度

      反射

      定义:

      • Java语言中,用来在运行时,查看和修改类内部结构的技术

      得到class对象的方式

      • Class.forName(字符串全路径)
      • 类名.class
      • 对象.getClass()

      类的信息

      • getName()

      • getSimpleName()

      • getInterfaces()

        • Class<?>[] interfaces = String.class.getInterfaces();
              System.out.println(Arrays.toString(interfaces));
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14

          - `isArray()` //是否为数组

          - `isEnum()`//是否为枚举

          - `isInterface()` //是否为接口

          - `isPrimitive() `//是否为基本类型

          - `isAssignableFrom(指定类型)` //是否为指定类型的父类

          - ```java
          boolean assignableFrom = Number.class.isAssignableFrom(Double.class);
          System.out.println(assignableFrom);
      • getModifiers()//得到修饰符

      得到属性

      • Field[] getDeclaredFields()//得到所有属性
      • Field getDeclaredField("指定属性")//得到某一个指定
      • getFields()//得到public的属性
      • getField("属性名")

      得到方法

      • Method getDeclaredMethod(String name, Class<?>... parameterTypes)
      • Method[] getDeclaredMethods()

      得到构造器

      • getDeclaredConstructoes
      • getDeclaredConstructoe(类名.class)
      • getConstructors
      • getConstructor

      操作

      • newInstance() //得到该类实例,默认调用无参构造器创建实例

      实例如下

      • public class Test {
            
            public static void main(String[] args) throws Throwable, Exception{
                //获取类的实例
                Class<?> stu = Student.class;
                Field df;
                try {
                    //返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
                    df = stu.getDeclaredField("name");
                    //获取属性的名字
                    System.out.println(df.getName());
                    //获取属性的类型
                    System.out.println(df.getType());
                    //返回此类或接口以整数编码的 Java 语言修饰符,使用Modifier类解码
                    System.out.println(Modifier.toString(df.getModifiers()));
                    //设值可以访问私有属性
                    df.setAccessible(true);
                    //获取属性的值 传入一个对象
                    System.out.println(df.get(Student.class.newInstance()));
                    
                    //获得指定的方法
                    Method dm = stu.getDeclaredMethod("eat");
                    //获得方法名字
                    System.out.println(dm.getName());
                    //获得方法的返回值类型
                    System.out.println(dm.getReturnType());
                    System.out.println(stu.getDeclaredMethod("sum",double.class,double.class).getReturnType());
                    //调用方法
                    Method method = Student.class.getMethod("sum",double.class,double.class);
                    System.out.println(method.invoke(Student.class.newInstance(),55,66));
                    
                } catch (NoSuchFieldException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SecurityException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        
            }
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24

        # 注解(Annotation)

        @WebServlet、@WebFilter、@WebListener

        配置信息

        - XML
        - 注解

        说明

        - 标注在类或者属性或者方法等代码单元上,用以提供额外的配置信息的技术,注解本身没有任何效果,注解处理器负责处理和对程序产生影响

        编写方法:

        ```java
        public @interface ClassCommite{
        //方法,default给定初值,没有default,则使用时必填
        String duty() default "一般委员";
        int level();
        //表示复数,用数组
        String[] onDutyDates() default {"周一","周二"};
        }

      使用场景:

      • 在编译期间,用于给编译器提供信息 @override
      • 在编译或者部署时,用于生产代码或者执行某些部署操作
      • ★在运行期,给代码单元添加配置信息

      元注解(注解的注解)

      • @Target 指定注解可以使用的目标,由ElementType指定,主要的值有:TYPE、FIELD、METHOD、CONSTRURCTOR、PARAMETER

      • @Retention 保留到哪个阶段,由RententionPolicy指定,值有:SOURCE(源码,编译器)、RUNTIME(运行期)、CLASS(class文件),通常指定为RUNTIME;默认为class

      • @Inherited 该注解是否被子类继承A , B extends A

      • @Documented 是否被加入到文档中

      • @Repeatable jdk1.8新增 注解是否可以重复加在同一个组件上

      • 例:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface TableFieldLimit {
        //可空
        boolean nullable() default true;
        //长度
        int length(); //长度 = ? - 2;
        //注释
        String comment() default "";
        }

      本质

      • 本质是一个继承了Annotation的一个接口,注解类型可以强制转换为Annotation,所有的属性实际上是方法
      • Anotation.annotationType => 返回具体的annotation类型
      • Anotation.annotationType == WebServlet.class 可以通过这种比较

      特殊的属性

      • value,默认属性 ,@WebServlet(“/user”) ===>value属性
        • 意思就是,假如给注解里面加一个名叫value()的方法,那么在使用时,不用谢value=多少,可以直接写值

      读取注解

      • 反射中使用Class或者Method或者Field的getDeclaredAnnotation方法能够得到的相应的注解
      • isAnnotaionPresent 判断是否被该注解标记
      • getAnnotation =>Anonotation[]

      解析注解

      • 通过反射,在类、属性、方法等获取注解API如下
        • isAnnotationPresent(Class annoType)是否被指定注解标记
        • getAnnotation(Class anno Type)得到某个注解
        • getAnonotation得到所有注解
        • 通过Annotation的方法获取具体的值

      扩展

      • lombok神器及其实现

      • 安装步骤:

        • 1、 https://projectlombok.org/download 下载lombok 支持jar包lombok.jar
        • 2、 将 lombok.jar 放在eclipse安装根目录下
        • 3、命令行执行lombok.jar,安装lombok.jar
          • java -jar D:\DEV_ENV\eclipse\lombok.jar
        • 4、若出现Can’t find IDE弹出框后,点击确定,并点击Specify location选择eclipse位置,选择后点击Install/Update按钮安装
        • 5、安装成功标志:安装后,弹出框会消失,去eclipse根目录下,查看配置文件eclipse.ini,会多一行lombok.jar的配置项,说明lombok安装成功
      • 实例:

        • @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class User implements Serializable{
              @Id
              private int userId;
              private String userAccount;
              private	String userPassword;
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37

          # 单元测试

          覆盖所有的执行路径

          一份"活的"文档

          一份契约,支持重构(refactoring)

          使用方法:

          - 1.导包
          - 2.测试类继承TestCase类

          ```java
          方式一:
          public class TestStringUtil extends TestCase{
          public void testCamelCaseToUnderscore() {
          assertNotNull("判断的内容");
          assertEquals("abc", StringUtil.camelCaseToUnderScore("Abc"));
          assertEquals("a_bc", StringUtil.camelCaseToUnderScore("aBc"));
          assertEquals("a_b_c", StringUtil.camelCaseToUnderScore("aBC"));
          }
          }
          方式二:
          @Test:代表当前测试方法
          @Ignore:代表忽略当前方法
          public class TestSession{
          @Test
          @Ignore
          public void testFindById() {
          Session<User> session = new SessionImpl<>();
          User user = session.findById(User.class, 1);
          assertEquals("root", user.getUserAccount());
          assertEquals("123456", user.getUserPassword());
          System.out.println(user);
          }

      自己小总结

      监听器Listener
      统计访问次数
      统计访问人数
      过滤器Filter
      过滤编码集
      过滤重复请求
      过滤用户请求(拦截非登录状态跳转)
      cookie
      30秒免登录
      session
      保存登录后用户信息

      自写框架

      • 目的:
        • java基础综合练习,提升编码能力
        • 熟悉框架的原理
      • 两个框架:
        • ORM
        • MVC

      ORM

      对象-关系-映射 Object-Relation-Mapping

      把一个java对象和一条数据块数据进行映射绑定

      MVC

      ORM:对象关系映射 数据库查询 数据持久化

      MVC:(Model-View-Controller 模型-视图-控制器)解决Web层一系列问题,代替Servlet

      • 一个请求对应一个servlet类 url<=>对应一段代码(方法)
      • Servlet代码侵入性高
        • extends HttpServlet 不能继承其他父类
        • doGet/doPost
        • 方法参数 request/response
      • 接受参数getParameter
      • 参数的格式转换
      • 跳转代码很长
        • 通用模式 请求->servlet(处理业务) ->js(显示页面)

      目标

      • 请求映射到方法(注解)
      • 将请求参数自动绑定到方法参数,并进行自动类型转换
      • 根据返回的字符串自动跳转到jsp
        • return ‘productPage.jsp’
      • 自动json转换,返回一个java对象,自动转位json字符串

      思路

      • 前置Sevlet=>接收所有请求
      • 根据请求路径,查找对应的处理方法,若无,报错,若有,调用
      • 处理方法返回jsp对应字符串,转发到对应的jsp

      @RequestMapping 请求映射,把请求对应到一个方法

      Maven

      什么是Maven

      • 专门用于构建和管理Java相关项目的工具
        • 例如:项目名、包路径、依赖外部jar包、jdk版本、项目描述、网站、编译过程…

      POM.xml => 项目对象模型

      是什么详解?

      • 构建工具 编译打包,从源码构建成成品(jar包,war包)
      • 依赖管理工具 “不要重复造轮子” 管理外部的jar包
      • 项目信息聚合工具 项目相关信息

      安装方式

      • 在Linux的md文件夹中

      使用方式

      1
      2
      3
      4
      #创建项目,没有指定目录的话,在哪里输入,就生成在哪里
      mvn archetype:generate -DarchetypeCatalog=internal -DgroupId=com.woniuxy.build -DartifactId=mavenDemo -Dversion=1.0
      #在pom.xml的目录下执行该命令,编译并运行javaSE 项目
      mvn clean compile exec:java -Dexec.mainClass="com.woniuxy.build.App"

      理念:约定优于配置

      文件结构

      项目的约定:

      • src => 源码
        • main => 主要内容
          • java => java源码
          • resources=> 配置文件
        • test => 测试
          • java => java源码
          • resources=> 配置文件
      • pom.xml 项目整体配置
      • target 编译过后产生的文件

      生命周期

      初始化 ->编译 -> 测试(执行单元测试) -> 打包 -> 集成测试 -> 安装(到本地) ->部署

      使用方式

      在pom.xml同级路径下,执行以下命令,注意命令之间需要拥有顺序

      • mvn clean
      • mvn compile
      • mvn test
      • mvn package
      • mvn install
      • mvn clean install

      创建maven文件时,需要注意的GAV

      • groupid(一个公司),例:com.woniu.com
      • artifactId(项目名)
      • version(版本)
      • type
      • classfier(识别符)

      maven仓库文件去哪里找

      依赖范围:

      • 说明:项目不同的阶段引入到classpath中的依赖是不同的
      • compile(默认)、test(测试)、provided(环境提供)、runtime(运行时)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      具体实例:
      依赖范围在pom.xml中如何体现?
      pom文件如下配置:
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
      </dependency>

      依赖传递

      • 说明:只有compile和runtime的依赖是传递的
      • A -> B -> C
        • A -> B
        • A -> C
      • A->C简单传递依赖
        • A->B->C
      • A -> C(0.2)最短路径
        • A->B-C(0.1)
        • A->C(0.2)
      • A->B->C(0.1)第一声明优先原则
        • A->B->C(0.1)
        • A->D->C(0.2)

      仓库

      查找顺序

      • 本地 -> 私服 -> 中央仓库

      Profile 身份

      • 开发环境配置 : jar不稳定
      • 生产环境配置 : jar 稳定的

      问题及答案

      Date日期增加和减少

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      import java.text.Format;
      import java.text.SimpleDateFormat;
      import java.util.Calendar;
      import java.util.Date;

      public class $ {

      public static void main(String[] args) {
      Format f = new SimpleDateFormat("yyyy-MM-dd");

      Date today = new Date();
      System.out.println("今天是:" + f.format(today));

      Calendar c = Calendar.getInstance();
      c.setTime(today);
      c.add(Calendar.DAY_OF_MONTH, 1);// 今天+1天

      Date tomorrow = c.getTime();
      System.out.println("明天是:" + f.format(tomorrow));
      }
      }

      结果:
      今天是:2013-10-09
      明天是:2013-10-10

      eclipse复制粘贴项目,需要修改的几处地方

      • 1、更改项目名字
      • 2、修改访问的根目录:项目名右键 –> Properties –> Web Project Setting
      • 3、修改对应工程下的.setting文件夹下的org.eclipse.wst.common.component文件
        • 设置Window->show view->navigator才能看到
      0%