第4节:Java基础 - 必知必会(中)

第4节:Java基础 - 必知必会(中)

本小节是Java基础篇章的第二小节,主要讲述抽象类与接口的区别,注解以及反射等知识点。

一、抽象类和接口有什么区别

抽象类和接口的主要区别可以总结如下:

  • 抽象类中可以没有抽象方法,JDK8版本开始提供了接口总方法的default实现
  • 抽象类和类一样是单继承的;接口可以实现多个父类
  • 抽象类中可以存在普通的成员变量;接口中的变量必须是static final类型的,必须被初始化,接口中只能有常量,没有变量

    解析

    在Java中,我们用abstract来定义抽象类,通过interface关键字来定义接口。接口和抽象类中都可以定义抽象方法,然后交由其实现类来实现该抽象方法。

    抽象类和接口应该如何选择?分别在什么情况下使用呢?

根据抽象类和接口的不同之处,当我们仅仅需要定义一些抽象方法而不需要其余二外的具体方法或者变量的时候,我们嗯可以使用接口。反之,则需要使用抽象类,因为抽象类中可以有非抽象方法和变量

默认方法

  既然说到了JDK8接口中的方法可以实现,那么我们来看下default方法的具体实现。我们先给出一个接口中的default方法Demo,如下所示:

public interface MyInterface {
    // 定义一个已经实现的方法,使用default表明
    default void say(String message){
        System.out.println("Hello "+message);
    }
    // 普通的抽象方法
    void test();
}

  当一个类实现该接口时,可以继承到该接口中的默认方法,如下所示:

public interface MyInterface {
    // 定义一个已经实现的方法,使用default表明
    default void say(String message){
        System.out.println("Hello "+message);
    }
    // 普通的抽象方法
    void test();
}

class MyClass implements MyInterface{
    @Override
    public void test() {
        System.out.println("test...");
    }
}
class Main{
    public static void main(String[] args) {
        MyClass client = new MyClass();
        client.test();
        client.say("World...");
    }
}

  这样的话,大家就会有疑问,如果两个接口中存在同样的默认方法,实现类继承的是哪一个呢?Demo如下:

public interface MyInterface {
    // 定义一个已经实现的方法,使用default表明
    default void say(String message){
        System.out.println("Hello "+message);
    }
    // 普通的抽象方法
    void test();
}
interface MyInterface2{
    // 定义一个已经实现的方法,使用default表明
    default void say(String message){
        System.out.println("[2]-Hello "+message);
    }
}
// 此处会编译错误
class MyClass implements MyInterface, MyInterface2{
    @Override
    public void test() {
        System.out.println("test...");
    }
}

这个时候,实现类那里会编译错误 .我们有两种处理方式,如下所示:

  • 重写多个接口中的相同的默认方法
  • 在实现类中指定要使用哪个接口中的默认方法

a、重写多个接口中的相同的默认方法

class MyClass implements MyInterface, MyInterface2{
    @Override
    public void say(String message) {
        System.out.println("[Client]-Hello "+message);
    }
    @Override
    public void test() {
        System.out.println("test...");
    }
}

b、在实现类中指定要使用哪个接口中的默认方法:

class MyClass implements MyInterface, MyInterface2{
    // 手动指定哪个默认方法生效
    public void say(String message) {
        MyInterface.super.say(message);
    }
    @Override
    public void test() {
        System.out.println("test...");
    }
}

那么JDK8中为什么会出现默认方法呢?

使用接口,使得我们可以面向抽象编程,但是其有一个缺点就是当接口中有改动的时候,需要修改所有的实现类。在JDK8中,为了给已经存在的接口增加新的方法并且不影响已有的实现,所以引入了接口中的默认方法实现。

默认方法允许在不打破现有继承体系的基础上改进接口,解决了接口的修改与现有的实现不兼容的问题。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。在我们实际开发中,接口的默认方法应该谨慎使用,因为在复杂的继承体系中,默认方法可能引起歧义和编译错误

二、java中的8中基本数据类型及其取值范围

Java种的8种基本数据类型分别是:byte,short,int,long,float,double,char以及boolean。boolean类型的取值为true和false两种,其余每一种基本类型都占有一定的字节,并且拥有着最大值和最小值。比如int的取值范围为 Integer.MIN_VALUE 到 Integer.MAX_VALUE。这个题目的答案,我希望大家可以自己动手输入代码来一一查看以加深记忆。这里给出每种基本类型所占用的字节数:

  • byte:1字节
  • short:2字节
  • int:4个字节
  • long:8字节
  • float:4字节
  • double:8字节
  • char:2字节
  • boolean:Java规范中并没有规定boolean类型所占字节数

解析:

这是一个特别基础的题目,面试时候基本会考察各个基本类型所占的字节数,需要准确记忆与理解。关于取值范围,如果实在记忆有点缺失,可以和面试官说通过哪个字段可以获取到其取值范围也算尚可

三、Java中的元素注解有哪些?

Java中提供了4个元注解,元注解的作用是负责注解其它注解。

@Target

说明注解所修饰的对象范围,关键源码如下:

public @interface Target {
    ElementType[] value();
}
public enum ElementType {
  TYPE,FIELD,METHOD,PARAMETED,CONSTRUCTOR,LOCAL_VARIABLE,ANNOCATION_TYPE,PACKAGE,TYPE_PARAMETER,TYPE_USE
} 

例如,如下的注解使用@Target标注,表明MyAnn注解就只能作用 在类/接口和方法上。

@Target({ElementType.TYPE, ElementType.METHOD}) public @interface MyAnn { }

@Rentention

保留策略定义了该注解被保留的时间长短。关键源码如下:

public @interface Retention { RetentionPolicy value(); } public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }

其中,SOURCE:表示在源文件中有效(即源文件保留);CLASS:表示在class文件中有效(即class保留);RUNTIME:表示在运行时有效(即运行时保留)。例如,@Retention(RetentionPolicy.RUNTIME)标注表示该注解在运行时有效。

@Documented

该注解用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被javadoc此类的工具文档化。Documented是一个标记注解,没有成员。关键源码如下:

public @interface Documented {
}

  

@Inherited

该注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。关键源码如下:

public @interface Inherited {
}

  

解析:

Java中的注解是一个基础知识点,我们在程序中频繁的使用注解。使用注解可以代替配置文件,比如SpringBoot就是提供了大量的注解来代替配置文件,从而极大的方便了Web项目的搭建与开发。那么,我们再来详细阐述下Java中的注解吧。

注解的作用:

代替繁杂的配置文件,简化开发。

何定义一个注解?

定义注解类不能使用class、enum以及interface,必须使用@interface。下边是一个简单的注解定义:

public @interface MyAnn{}

如何定义注解的属性?

public @interface MyAnn {
    String value();
    int value1();
}
// 使用注解MyAnn,可以设置属性
@MyAnn(value1=100,value="hello")
public class MyClass {
}

  

定义注解时候的value就是属性,看着是一个方法,但我们称它为属性。当为注解指定属性后,那么在使用注解时就必须要给属性赋值了。

四、Java中反射机制

反射机制是指在运行中,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性。即动态获取信息和动态调用对象方法的功能称为反射机制。

反射机制的作用

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法,生成动态代理

    与反射相关的类:

  • Class:表示类,用于获取类的相关信息
  • Field:表示成员变量,用于获取实例变量和静态变量等
  • Method:表示方法,用于获取类中的方法参数和方法类型等
  • Constructor:表示构造器,用于获取构造器的相关参数和类型等

这里我们讲述下如何获取Class类吧,获取Class类有三种基本方式:

(1)通过类名称.class来获取Class类对象:

Class c = int.class;
Class c = int[ ].class;
Class c = String.class

  

(2)通过对象.getClass( )方法来获取Class类对象:

Class c = obj.getClass( );

(3)通过类名称加载类Class.forName( ),只要有类名称就可以得到Class:

Class c = Class.forName(“cn.ywq.Demo”);

接下来,我们给出一个以反射方式来创建对象的Demo:

package com.ywq;

public class Demo1 {
    public static void main(String[] args) throws Exception {
        String className = "com.ywq.User";
        // 获取Class对象
        Class clazz = Class.forName(className);
        // 创建User对象
        User user = (User)clazz.newInstance();
        // 和普通对象一样,可以设置属性值
        user.setUsername("yangwenqiang");
        user.setPassword("19931020");

        System.out.println(user);
    }
}

class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + "]";
    }
}

附加

clazz.newInstance()和clazz.new()区别总结如下:

1.构造方法实例化, 会判断实例化的对象的Class是否已经加载,如果没有加载需先加载类,然后初始化类,返回一个实例.

clazz.newInstance()方法必须在类加载完成之后才能调用.也就是说,这一步不会有类加载的步骤.类加载必须在此之前加载完成,否则不能调用该方法.

比如Class.forName(Stirng clazzName)包含加载和连接两个阶段,连接阶段包含:验证,准备,解析三个阶段;

然后初始化类,返回一个实例

2.clazz调用的是无参构造方法,而实例化构造方法使用有参构造方法. 当然需要public修饰. 反正要能访问的到.

3.clazz反射可以用来解耦合,动态的构造实例. 比如IOC控制反转,以及基于接口编程.可以把实现类或者子类,强转为接口类或父。

关于反射这块的详细API接口介绍,建议大家参考官方提供的API接口文档 。

总结

本小节是Java基础篇章的第二小节,本小节中介绍的接口和抽象类的区别,建议大家熟练掌握。注解和反射机制在Java基础中具有一定的难度,希望大家可以多加理解与掌握。

 

原文地址:https://www.cnblogs.com/csushl/p/11964872.html

时间: 2024-10-27 07:20:15

第4节:Java基础 - 必知必会(中)的相关文章

第5节:Java基础 - 必知必会(下)

第5节:Java基础 - 必知必会(下) 本小节是Java基础篇章的第三小节,主要讲述Java中的Exception与Error,JIT编译器以及值传递与引用传递的知识点. 一.Java中的Exception和Error有什么区别 Exception和Error的主要区别可以概括如下: Exception是程序正常运行中预料到可能出现的错误,并且应该被捕获并进行相应处理,是一种异常现象. Error是正常情况下不可能发生的错误,Error会导致JVM处于已追踪不可恢复的状态,不需要捕获处理,比如

图解 & 深入浅出Java初始化与清理:构造器必知必会

Writer      :BYSocket(泥沙砖瓦浆木匠) 微         博:BYSocket 豆         瓣:BYSocket FaceBook:BYSocket Twitter    :BYSocket 在面向对象编程中,编程人员应该在意"资源".比如 ? 1 <font color="#000000">String hello = "hello": </font> 在代码中,我们很在意在内存中Stri

迈向高阶:优秀Android程序员必知必会的网络基础

1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用的工具类,到后来Google开源的比较完善丰富的Volley,再到如今比较流行的Okhttp.Retrofit. 要想理解他们之间存在的异同(或者具体点说,要想更深入地掌握Android开发中的网络通信技术),必须对网络基础知识.Android网络框架的基本原理等做到心中有数.信手拈来,关键时刻才能

一个老师程序员说:这是学Java 必知必会的 20 种常用类库和 API

一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车.<Effective Java>的作者Joshua Bloch曾经说过:"建议使用现有的API来开发,而不是重复造轮子".在本文中,我将分享一些Java开发人员应该熟悉的最有用的和必要的库和API.顺便说一句,这里不包括框架,如Spring和Hibernate因为他们非常有名,都有特定的功能.最后,如果大家如果在自学遇到困难,想找一个java的学习环境,可以加入我们的java学习圈,点击我加入吧,会节约很多时

SSL证书必知必会:数字证书及CA基础知识

SSL证书必知必会:数字证书及CA基础知识 数字证书 数字证书是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式,数字证书不是数字***,而是身份认证机构盖在数字***上的一个章或印(或者说加在数字***上的一个签名).它是由权威机构--CA机构,又称为证书授权(Certificate Authority)中心发行的,人们可以在网上用它来识别对方的身份.最简单的证书包含一个公开密钥.名称以及证书授权中心的数字签名.数字证书的一个重要的特征就是只在特

.NET零基础入门09:SQL必知必会

一:前言 仿佛到了更进一步的时候了,每一个程序员迟早都会遇到数据存储的问题.我们拿什么来存储程序产生的数据?举例来说,用什么来存储我们的打老鼠游戏每次的成绩呢?选择如下: 1:内存中.缺点,退出游戏,数据就没了: 2:文件中.好办法!缺点,自己解析文本,把文本变成我们程序中的数据,这个解析的过程叫做协议.协议这个词听上去够恐怖吧,实际上说白了无非就是数据格式怎么样,API接口怎么样之类的东东. 3:数据库.好办法!好吧,数据库文件其实也就是硬盘上的文件,只不过数据库本身就已经为我们定义好了数据格

基础入门_Python-模块和包.深入Celery之常用架构/方案选型/必知必会?

简单介绍: 说明: 此模块是一个专注于分布式消息传递的异步任务队列,所谓任务就是消息,消息中的有效载荷中包含要执行的任务需要的全部数据 几大特性: 1. Celery易于使用和维护,且不需要配置文件,默认配置启动时自动写入消息代理. 2. Celery高可用,连接丢失或失败时客户端或消费者会自动重试,并且可通过消息代理的双主/主从模式来提高高可用性 3. Celery快速,单个进程每分钟可处理百万任务,且优化后可保持往返延迟在亚毫秒级别 4. Celery灵活,几乎所有部分都支持扩展或单独使用,

《MySQL必知必会学习笔记》:正则表达式

正则表达式的应用 前面的几节的过滤例子允许用匹配.比较和通配操作符来寻找数据.对于基本的数据过滤,这样就足够了.但是随着过滤条件的复杂性的增加,where子句本身的复杂性也有必要增加.这也就是正则表达式变得有用的地方. 正则表达式是用来匹配文本中特殊的字符集合. 正则表达式不是自己第一次见,在JAVA/C++ 这些语言中,都有正则表达式,不过他们的用途是一样的,都是匹配文本中的字符串.可能具体的用法不太一样,但也差不多.下面将一一进行学习.介绍. 基本字符的匹配 当我们想查找某列中的字符中是否有

必知必会JVM垃圾回收——对象搜索算法与回收算法

垃圾回收(GC)是JVM的一大杀器,它使程序员可以更高效地专注于程序的开发设计,而不用过多地考虑对象的创建销毁等操作.但是这并不是说程序员不需要了解GC.GC只是Java编程中一项自动化工具,任何一个工具都有它适用的范围,当超出它的范围的时候,可能它将不是那么自动,而是需要人工去了解与适应地适用. 拥有一定工作年限的程序员,在工作期间肯定会经常碰到像内存溢出.内存泄露.高并发的场景.这时候在应对这些问题或场景时,如果对GC不了解,很可能会成为个人的发展瓶颈. 接下来的两文将详细学习下JVM中垃圾