java基础

目录

Java和C语言有什么区别?Java好在哪里?

语法不同:   

应用领域不同:

怎么理解Java的跨平台性,一次编译到处运行?

什么是编译:

面向对象和面向过程的区别?

如何理解面向对象三大特性:封装、继承、多态?

类的抽象与封装

封装:(encapsulation)

继承(extends)

使用场景:

语法:

使用继承的注意点

super关键字与构造方法链

方法重写

多态(Ploymorphism)

多态的实现原理--动态绑定:

为什么重写equals方法还要重写hashcode方法?

HashMap原理

为什么要重写equals方法

深克隆和浅克隆

反射相关

什么是反射:

反射机制是什么:

反射原理:

反射的优缺点:

注解的实现原理

Lambda表达式的优缺点?

Stream流式编程

设计模式

设计模式的类型

​设计模式的六大原则

1.开闭原则

2.里氏代换原则

3.依赖倒转原则

4.接口隔离原则

5.迪米特法则,又称最少知道原则

6.合成复用原则

JDK1.8新特性Optional

三元运算符



 

Java和C语言有什么区别?Java好在哪里?

  1. 设计思路不一样,

C语言是面向过程的语言,执行效率高,java是面向对象的语言,执行效率比C语言低。

  1. 通用性不同:

C语言不能跨平台,java可以跨平台直接移植,只要有安装java虚拟机(jvm)就可以了。

语法不同:   

  • 基本数据类型不同

C语言是 int  short long char float double 还有一些特殊类型结构体,指针,联合体等,数组,字符串。

java是 int short long float byte double char boolean ,C语言的基本类型的位数和操作系统和机器相关,而java是固定的。

  • 文件组织方式不一样,C语言会把全局变量和方法的声明,放在一个文件里面,叫做头文件,而java是以类来组织文件的。

应用领域不同:

C语言主要用于驱动开发,操作系统,内核开发,嵌入式(单机片),交换机,路由器等网络设备的开发;

java主要是企业应用开发,包括服务器端开发,嵌入式领域,大数据技术,网站领域等。

怎么理解Java的跨平台性,一次编译到处运行?

什么是编译:

编译就是使用编译器把高级语言变成计算机可以识别的二进制语言;

java是一种特殊的高级语言,java程序的执行过程必须经过先编译,后解释两个步骤,首先java源文件被以为字节码文件,然后由jvm解释执行。java编译产生的不是针对特定平台的机器码,而是一种与平台无关的字节码文件(.class文件)。相同的字节码在不同平台上直接运行原本是不可能的,但通过中间的转化器就可以实现了一次编译,到处运行的效果,jvm就是这个转换器,不同平台上的jvm是不同的,但提供给java字节码程序的接口是完全相同的,所以这些字节码不面向任何平台,只面向jvm。

面向对象和面向过程的区别?

面向对象(OOP)是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

面向过程就是分析出问题的所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

如何理解面向对象三大特性:封装、继承、多态?

类的抽象与封装

类的抽象是将类的实现和使用分离,而类的封装是将实现的细节封装起来并且对用户隐藏,用户只需会用就行。

访问权限修饰符的作用域范围从大到小:public --> proetected --> default --> private

import和package关键字的区别

package表明当前类属于那个包空间,永远放在第一行。import是用于导入其他包的类。

封装:(encapsulation)

封装的本质就是通过定义类,并且给类的属性和方法加上访问权限,用于控制在程序中属性的修改的访问级别。简单来说,通过访问权限控制,隐藏重要数据,避免随便修改数据,只对外暴露不会影响类的数据安全的公共方法。

继承(extends)

从已存在的类中定义新的类,实现代码复用,这称为继承。继承在软件重用方面是一个重要且功能强大的特征。

使用场景:

类与对象的关系:一个类具有同一类型的对象的属性和行为.

类于类的关系:有的时候,不同类之间也有一些共同的特征和行为,将这些共同特征和行为提取出来,统一放在一个类中,作为一个通用类。这时可以定义特定的类继承该通用类,这些特定的类继承通用类的可访问数据域和方法。

语法:

使用extends关键字。实例:pulbic subClass extends Student{}

使用继承的注意点

  • 父类的私有数据和方法无法被继承,因为private修饰的变量和方法仅限于类的内部。但我们可以通过父类提供的公共访问器/修改器来进行访问和修改(get,set);
  • 和传统的理解不同,子类并不是父类的子集。实际上,一个子类通常比父类包含更多的数据和方法。子类是对父类的扩展,父类仅提供数据域和方法。
  • 继承表示"是一种"(is-a)(什么是什么)关系,即一个父类与他的子类必须存在 是一种 关系。例如老虎是动物等。
  • java只支持单继承,即一个类只能继承一个父类。然而,要实现多重继承可以通过接口来完成。

super关键字与构造方法链

super关键字指代父类,可用于调用父类中的普通方法好构造方法。而this则是对象调用对象的引用。

方法重写

  • 子类从父类中继承方法,但有时候,需要根据子类的需求来修改父类的方法实现,这称之为方法重写。
  • 注意点:
  • 静态方法可以被继承,但不能被重写。因为静态方法输入类本身,若子类定义了同名的静态方法,则与父类的静态方法毫无关联。要调用父类同名静态方法,父类名.静态方法。
  • 只有实例方法时可访问(即非私有)。他才能被子类进行方法重写。
  • 方法重写是多态实现的重要手段,可以说继承就是为了多态而准备的,继承就是多态实现的前提。

多态(Ploymorphism)

多态就是同一事物的多种不同形态。

实现多态的前提:

  • 继承
  • 重写
  • 父类引用指向子类对象

多态的实现原理--动态绑定:

一个变量必须声明某种类型,变量的类型成为他的声明类型。如果一个引用类型变量,那么他可以是一个null值或者是对该声明类型的引用。但变量的时机类型是引用变量引用的对象的类 。所以调用哪一个方法实际上是由实际类型所决定。这就是动态绑定。

为什么重写equals方法还要重写hashcode方法?

1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率

2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现

HashMap原理

hashmap存储数据的时候,是取的key值的哈希值,然后计算数组下标,采用链地址解决冲突,然后进行存储;取数据的时候,依然要先要获取到hash值,找到数组下标,然后for遍历链表集合,进行比较是否有对应的key;

不管是put还是get的时候,都需要得到key的哈希值,去定位key的数组小标;

在get的时候,需要调用equals方法比较是否有相等的key存储过。

“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”。

== 比较的是变量存储的地址

为什么要重写equals方法

如果不重写equals方法,使用object的equals方法,他比较是存储的地址,而不是值

我们知道判断的时候先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true。

.HashCode被设计用来提高性能。

equals()方法与hashCode()方法的区别在于:

如果两个对象相等(equal),那么他们一定有相同的哈希值。 如果两个对象的哈希值相同,但他们未必相等(equal)。

注:== 表示两对象内存地址相同

 

深克隆和浅克隆

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原属性所指向的对象的内存地址。

深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。

如图:

pos:当前对象的地址;

son:son属性所指向的地址;

name:对象的name属性。

反射相关

什么是反射:

反射是在程序运行时,能动态查看和修改他的状态;

反射机制是什么:

在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法,对于任意一个对象都能调整他的任意一个方法和属性。

这种动态获取信息以及动态调用对象的方法和功能称为java语言反射机制。

通俗的理解:在运行期间可以对类的内容进行操作。

反射原理:

  1. 编写的文件源文件.java保存在本地磁盘。
  2. 编译生成字节码文件.class
  3. 通过jvm将字节码加载到内存中
  4. 将字节码加载到内存当中,把整个字节码文件看到一个对象,对象类型为Class类型。
  5. 获得对象,就可以获得自己吗文件当中所有内容,所有内容包括:构造器,方法,属性。

反射的优缺点:

大幅度提高开发效率,有脸框架可以提高开发效率。

发射的效率比非反射方式的效率低。

反射可以暴露的所有细节,没底线,不安全。

注解的实现原理

1,什么是注解

注解也叫元数据,例如我们常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解

一般常用的注解可以分为三类:

  1. 一类是Java自带的标准注解,包括@Override(标明重写某个方法)、@Deprecated(标明某个类或方法过时)和@SuppressWarnings(标明要忽略的警告),使用这些注解后编译器就会进行检查。

  2. 一类为元注解,元注解是用于定义注解的注解,包括@Retention(标明注解被保留的阶段)、@Target(标明注解使用的范围)、@Inherited(标明注解可继承)、@Documented(标明是否生成javadoc文档)

  3. 一类为自定义注解,可以根据自己的需求定义注解

2. 注解的用途

注解: 是一种分散式的元数据,与源代码紧绑定。

xml:  是一种集中式的元数据,与源代码无绑定。

3. 注解的实现原理

  1. 注解声明
  2. 使用注解的元素
  3. 操作注解使其起作用(注解处理器)

Lambda表达式的优缺点?

优点:

1、代码更加简洁

2、减少匿名内部类的创建,节省资源

3、使用时不用去记忆所使用的接口和抽象函数

缺点:

1、不易于后期维护,必须熟悉lambda表达式和抽象函数中参数的类型

2、可读性差

Stream流式编程

Stream流常用方法

对于Stream流的常用方法,可以分成延迟方法和终结方法

  1. 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,支持链式调用(除了终结方法外,其余方法均为延迟方法)

  2. 终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持链式调用。常见的终结方法有 count 和forEach 方法

Stream流编程需要注意的点

Stream流属于管道流,只能被消费一次,也就是说第一个Stream流调用方法完毕之后,数据会流到下一个Stream流,并且该流会被关闭,再次使用该流去调用方法将会报错

stream流的好处:

使用stream流式编程不仅可以简化代码开发,增强可读性,还可以在不修改原来集合的基础上对数据进行过滤、映射等操作

设计模式

原文地址:https://www.runoob.com/design-pattern/design-pattern-intro.html

什么是GOF(四人帮,全拼Gang of Four):

在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。

四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。

  • 对接口编程而不是对实现编程。
  • 优先使用对象组合而不是继承。

设计模式的类型

根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,公共有23种设计模式,这些模式可以分为三大分类:创建型模式,结构性模式,行为型模式。另一类设计模式:J2EE设计模式

序号模式 & 描述包括
1创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 单例模式(Singleton Pattern)
  • 建造者模式(Builder Pattern)
  • 原型模式(Prototype Pattern)
2结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 过滤器模式(Filter、Criteria Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)
3行为型模式
这些设计模式特别关注对象之间的通信。
  • 责任链模式(Chain of Responsibility Pattern)
  • 命令模式(Command Pattern)
  • 解释器模式(Interpreter Pattern)
  • 迭代器模式(Iterator Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 观察者模式(Observer Pattern)
  • 状态模式(State Pattern)
  • 空对象模式(Null Object Pattern)
  • 策略模式(Strategy Pattern)
  • 模板模式(Template Pattern)
  • 访问者模式(Visitor Pattern)
4J2EE 模式
这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
  • MVC 模式(MVC Pattern)
  • 业务代表模式(Business Delegate Pattern)
  • 组合实体模式(Composite Entity Pattern)
  • 数据访问对象模式(Data Access Object Pattern)
  • 前端控制器模式(Front Controller Pattern)
  • 拦截过滤器模式(Intercepting Filter Pattern)
  • 服务定位器模式(Service Locator Pattern)
  • 传输对象模式(Transfer Object Pattern)

下面用一个图片来整体描述一下设计模式之间的关系:

设计模式之间的关系
设计模式的六大原则

1.开闭原则

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。

2.里氏代换原则

里氏代换原则是面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现,LSP是继承复用的基石,只有当派生类可以替换掉基类(基类就是父类,派生类就是子类),且软件单位的功能不收到影响时,基类才能真正被复用,而派生类也能够再基类的基础上增加新的行为。里氏替换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象类的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3.依赖倒转原则

这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4.接口隔离原则

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。他还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发,便于升级和维护的软件设计思想,他强调降低依赖,降低耦合。

5.迪米特法则,又称最少知道原则

一个实体当尽量少地与其他实体之间发生相互作用,使得系统功能模快相对独立。

6.合成复用原则

尽量使用合成/聚合的方式,而不是使用继承。

JDK1.8新特性Optional

Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional是个容器:他可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显示进行空值检测。

Optional类的引入很好的解决空指针异常。

类声明:

public final class Optional<T> {}

常用方法:

// 创建一个包装对象值为空的Optional对象
Optional<String> optStr = Optional.empty();
// 创建包装对象值非空的Optional对象
方法: public static <T> Optional<T> of(T value) 
Optional<String> optStr1 = Optional.of("optional");
// 创建包装对象值允许为空的Optional对象
方法: public static <T> Optional<T> ofNullable(T value)
Optional<String> optStr2 = Optional.ofNullable(null);
// 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
方法: public T get()
Optional<Integer> b = Optional.of(value2);
Integer integer = b.get();
// 如果值存在则使用该值执行需用实现的 , 否则不做任何事情。
方法: public void ifPresent(Consumer<? super T> consumer)
Optional<Integer> b = Optional.of(value2);
boolean present = b.isPresent();
//如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
方法: public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
// 如果getUsername不等于空,就得到里面的值,等于空等于null
Optional.ofNullable(user).map(a -> a.getUsername()).orElse(null)
//如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
方法: public Optional<T> filter(Predicate<? super T> predicate)

注意:orElse方法中的参数类型要和map中类型保持一致

三元运算符

public static int getNum() {
        int num1 = 10;
        int num2 = 20;
        int num3;
        // 如果num2小于num1为true时,num3等于30,false时等于0
        return num3 = num2 < num1 ? 30 : 0;
    }

 多线程:

1. 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥
2. 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥。
3. 同步:进程之间的关系不是相互排斥临界资源的关系,而是相互
依赖的关系。进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。
其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。
4. 并行:在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特种;在多处理器系统中,进程不仅可以交替执行,而且可以重叠执行。在多处理器上的程序才可实现并行处理。从而可知,
并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生。

5. 多线程:多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。

6. 异步:异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。
线程就是实现异步的一个方式。
异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。
   异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。
实现异步可以采用多线程技术或则交给另外的进程来处理。

 

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值