Java基础总结(初学者)

Java基础

java语言 库API(应用程序访问接口)
资产管理 分层思想
面向对象 接口使用
类型转换,转换为什么类型就要在什么类型中定义方法
JDK,JRE,JVM关系?
JDK>JRE>JVM
jdk开发程序,工具包 (jdk 1.8)
jre运行程序 运行环境
jvm虚拟机 翻译官 跨平台核心

Java的内存结构?
Java的内存结构就是JVM内存结构

java程序的运行原理?
1.源文件(java源代码)通过编译器编译成字节码文件class.
2.通过JVM中的解释器将字节码文件生成对应的可执行文件,运行
3.将编译后的程序加载到方法区,存储类信息
4.运行时,JVM创建线程来执行代码,在虚拟机栈和程序计数器分配独占的空间。根据方法区里的指令码,在虚拟机栈对线程进行操作,程序计数器保存线程代码执行到哪个位置

标识符
1.标识符是用来命名的,在Java中,我们可以对包、类、方法、变量、参数进行命名
2.标识符只能由数字、字母、下划线、美元符号组成;不能以数字开头、不建议用下划线、美元符号开头
3.必须以字母开头
1.类名首字母必须大写,包、方法、变量、参数的名称首字母小写
2.如果名称由多个多个单词组成,要满足驼峰命名规则(首字母小写,如果由多个单词组成,其它单词首字母大写)
3.常量名称,所有字母都大写,如果有多个单词组成,单词之间用下划线连接
4.在Java中 ,大小写是非常敏感的,A和a是不同的字符,
5.Java中有关键字、保留字,我们不能使用
6.抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾
7.pojo 类中的任何布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误

基本数据类型和引用数据类型有哪些?

基本数据类型有八种(存放保存的值,值类型 )
1.四种整数类型(byte,short,int,long)
2.两种浮点数类型(float,double)
3.一种字符类型 char
4.一种布尔类型 boolean
1.boolean:数据值只有true或flase,适用于逻辑运算,一个字节
2.char:字符型,数据在内存中占两个字节
3.byte:字节型,数据在内存中占一个字节,八个字符,表示的存储范围为—128~127
4.short:短整型,数据在内存中占两个字节。
5.int::整形,数据在内存中占用四个字节
6.long:长整型:数据在内存中占用八个字节,数后加L
7.float:单精度浮点型,数据在内存中占用四个字节,数后加F
8.double:双精度浮点型,数据在内存中占用八个字节
在Java中,默认的数据类型为int,默认的浮点数据类型为double。

引用数据类型(存放地址,类类型)
数据转化类型;?
自动转化类型:在执行过程中转化,不需要用户提前说明,字节多的转化为字节少的
强制转化类型 :字节少的转换为字节多的,必须在代码中声明,转换顺序不受限制
转换成什么就在什么方法里面()
接口
数组
对象

拆箱和装箱(手动,自动)
基本数据类型不是包装类,不能作为对象调用方法,所以提供了每个数据类型的包装类
int- ->Integer
char- ->Character

装箱:基本数据类型–>对应包装类
拆箱:包装类–>对应基本数据类型

包装类本质是一个对象,装箱时先在堆中new一个对象,再将基本数据类型的值赋给该对象的值value
一定不要使用==或者!=在包装类型和基本数据类型之间进行比较,一般使用equals()
当进行算数运算时,运到包装类型会进行自动拆箱,再对基本数据类型进行运算

基本数据类型转化为String类型+"",String.valueof(基本数据类型变量)
String类型转化为基本数据类型,包装类.parseXXX(“字符串”),Integer.parseInt(“字符串”)

简单数据类型包括什么?
字符串
基本数据类型

访问修饰符(权限修饰符)
1.public:公共的(项目内)
2.private:私有的,只能在当前类中访问(当前类中)
3.protected:受保护的(jar包中,和有继承关系的类中)
4.default:默认的 缺省的(jar包中)

在其它类中调用private参数列表,要用set,get 方法
默认构造方法,无参构造
java.lang,jar包默认导入

Java设计模式?

单例模式
特点
1.单例类只能有一个实例
2.单例类必须自己创建自己的唯一实例,自行实例化
3.单例类必须给所有其它对象提供这一实例,向整个系统提供这个实例
优点
单例模式确保某个类只有一个实例(减少了内存的开销)
避免对资源的多重占用
设置全局访问点,优化和共享资源的访问
缺点
一般没有接口,扩展困难
不利于代码调试
功能代码通常写在一个类中,如果功能设计不合理,很容易违背单一职责原则

单例模式的实现
构造器被private访问修饰符修饰,通过getInstance()获取实例

2.工厂模式(简单工厂模式,工厂模式,抽象工厂模式)
3.代理模式(动态代理,静态代理)
4.原型模式(复制粘贴)
5.适配器模式
6.装饰模式
7.观察者模式

(单例模式的分类)饿汉式和懒汉式的区别?
饿汉式是线程安全的,在类创建的时候就已经创建好一个静态对象,不再改变
懒汉式是在你真正用到的时候(第一次调用)才去建立这个单例对象(实例化)线程不安全,加载时没有生成单例
静态内部类
枚举类

什么是动态代理?
代理模式,在程序运行时,运用反射机制动态创建而成
动态代理是⼀种在不修改源码的情况下对⽅法进⾏增强(扩展方法功能)的技术

  1. 基于接⼝的动态代理,JDK官⽅提供,被代理类最少实现⼀个接⼝,如果没有则不能使⽤;
  2. 基于⼦类的动态代理,第三⽅cglib库提供。
    使用 代理⼯⼚实现动态代理

TCP(传输控制协议)和UDP(用户数据报协议)区别?
TCP面向连接(在收发数据前,必须和对方建立可靠的连接,UDP无连接(不建立连接,不需要维护连接,一台服务机可同时向多个客户机传输多个消息),
TCP对系统要求多
UDP程序简单
TCP更可靠(三次会话,流模式),面向字节流,udp面向报文(数据报模式),
TCP连接点到点,UDP连接方式更加多样化
TCP包头的最小长度为20字节,UDP信息包八个字节
TCP保证数据正确性,UDP不保证
TCP保证数据顺序,UDP不保证

TCP/IP协议是一个协议簇。里面包含许多协议,UDP是其中一个。
TCP/IP协议包括应用层,传输层,网络层,网络访问层

应用层包括
超文本传输协议HTTP,万维网的基本协议
文件传输协议TFTP
远程登录Telnet,远程访问其他主机
网络管理SNMP,监控网路设备,配置管理,统计信息收集,性能管理,安全管理
域名登录DNS,在Internet中将域名及其公共广播的网络节点转换成IP地址

网络层包括
Internet协议(IP协议)
Internet控制信息协议(ICMP)
地址解析协议(ARP)
反向地址解析协议(RARP)

网络访问层(主机到网络层)
包括IP地址与物理地址硬件的映射,将IP封装成帧,

静态方法与实例方法的区别?
1.无法实例化
2.只能从System.Object基类继承,普通能继承非static和非sealed类的任意一个类
3.不能继承接口,普通可继承多个接口
4.只包含静态成员,普通可包含静态和非静态成员
5.不能作为字段,方法参数,局部变量

Java中垃圾回收的目的?
查找和回收无用的对象。让jvm更有效的使用内存。
垃圾回收器的运行时间是不确定的,由jvm决定,jvm通常会感到内存紧缺的时候去执行垃圾回收操作。

Stringabc 同一个常量词
new Stringabc 堆中

类和对象的关系
类是对具有相同属性或功能的一类事物的抽象。
类是抽象的,对象是具体的
java是以类为基础的,对象是以类为基础创建的,
创建了某个类的实例。也就同时赋予这个对象属性与方法。
属性和方法是这个类和对象共有的

获取运行时,类的几种方式?
1.通过thread的get stack trace()
2.通过throwable.getStack Trace()

抽象类和接口的区别?
接口只包含方法不包含具体操作
都不能被实例化
1.接口只能包含抽象类方法(可能有默认方法),抽象类可以包含普通方法
2.接口只能定义静态常量属性,抽象类可以定义普通属性,也可以定义静态常量属性
3.接口不包括构造方法,抽象类里可以包含构造方法

接口的优点
1.降低了类与类之间的依赖关系(解耦合)
2.提高了程序的可扩展性
3.提供了一种标准服务(JDBC)

面向对象和面向过程的区别?
面向过程:以分步的方式解决问题。用方法组织代码。用函数一步步实现这些步骤,一个个调用
(性能高,在实例化时开销大)
方法,对象(具体)就是一个类(抽象)的实例,类不占内存
面向对象:以分类的方式解决问题。用类组织代码。一个系统分解成多个对象,对象是描述某个事务的行为(对象是由属性,类和方法构成的)(易维护,易复用,易扩展,开销大,性能低)
细节上用面向过程解决,整体上用面向对象把控。二者相辅相成并不是对立的。

面向对象
1.程序流程由用户在使用中决定
2.是一种编程术语,把数据以及对数据的操作放在一起,作为一个相互依存的整体。
面向过程
是一种以事件为中心的开发方法,自顶向下顺序执行,逐步求精,其程序结构按照功能划分为若干个基本模块,这些模块形成一个树状结构,各个模块功能上相对独立,每一个模块内部一般都是由顺序循环选择三种基本结构构成,其模块化实现的具体方法是使用子程序,程序流程在写程序时就已经决定了。

面向对象的三大特性?
1.封装。把客观事物封装成抽象的类。并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。要求:提供一个对外接口,至少有一个继承关系,把父类中子类拥有的共同属性封装起来,让子类继承,
2.继承。它可以使用现有类的所有功能,并在无需编写原来的类的情况下对这些功能进行扩展,子类拥有父类的全部属性和方法
3.多态。允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给他的子对象的特性以不同的方式运作。同一对象的多种形态,(方法重写,方法重载,都属于多态)

什么是多态?
多态性是指允许不同类的对象对同一消息做出响应。
1.参数化多态性
2.包含多态性
多态性语言具有灵活,抽象,行为共享,代码共享的优势,很好地解决了应用程序函数同名的问题。
多态性有两种表现形式,重载和覆盖

多态特点
低耦合,高扩展

多态分类
编译时多态:静态的方法重载
运行时多态:动态的,只有运行期间才能够确定使用的对象类型,才能确定变量引用指向的是那个实例

返回值类型return
结束方法,把结果返回给调用者
static静态方法,只能调用静态方法和静态变量
void 无返回值类型
其他类型(所有类型都可以)

方法名编写规则(驼峰法)

值的互换
有两个变量,让它们的值互换,定义第三方变量,把其中一个变量的值赋给第三方变量,再用另一个变量的值去给这个变量赋值,最后用第三方变量的值赋给这个另一个变量,完成指定互换。

类和方法
类就是抽象的,有具体属性(特征),不占内存
方法,就是类的实例(行为),调用类,具体的,占内存
第一个单词首字母小写,如果有多个单词组成,其它单词首字母大写

型参列表
形式参数组成的列表
public int add(int a,int b)
int a,int b型参列表,方法中的参数
接受实际数据
返回值数据要与返回值类型一致

参数
形式参数:接收用户调用方法传过来的参数值
实际参数:实际传递真实数据

参数的传递
基本数据类型(值传递)传递的是值的副本
引用数据类型(引用传递)传递的是引用地址

自定义引用类型
作用域(作用范围)
类作用域:在当前类中可以访问
局部作用域:在当前代码块(方法内)可以访问

成员变量和局部变量
成员变量:是在类中定义的变量(方法外部类的内部)
局部变量:是在方法内定义的变量
使用局部变量时,必须要初始化,否则会出现编译错误
使用成员变量时,可以不初始化,因为成员变量是默认值

成员变量和局部变量的区别?

1.在类中位置不同:
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
2.在内存中位置不同
成员变量:在堆内存
局部变量:在栈内存
3.生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法调用的完毕而消失
4.初始化值不同
成员变量:有默认值初始化
局部变量:没有默认值初始化,必须定义,赋值,然后才能使用
局部变量的名称可以和成员变量的名称一样,在方法中使用的时候,采用的是就近原则
成员变量是在类范围内定义的变量
局部变量是在一个方法内定义的变量

成员变量可以分为
1.实例属性(不用static修饰):随着实例属性的存在而存在
2.类属性(static修饰):随着类的存在而存在,成员变量无需显式初始化,系统会自动对其初始化
局部变量可分为
1.形参(形式参数):在整个方法内定义的变量,在整个方法内有效
2.方法局部变量(方法内定义):从定义这个变量开始到方法结束这一段时间内有效
3.代码块局部变量(代码块内定义):从定义这个变量开始到方法结束这一段时间内有效
局部变量除了形参外,都必须显式初始化,也就是要指定一个初始值,否则不能访问。
成员变量在所有类被实例化后,存在堆内存中,局部变量在所在方法调用时,存在栈内存空间中。

可变参数(args)
可变参数可以接受零个或多个参数接收一个数组,也可以不传递参数
可变参数必须在形参列表的最后的位置

方法重载和方法覆盖
1.方法重载overload,发生在同一个类中,与父类子类继承无关。
一个类中可以有两个或多个函数叫同一个名字,而他们的参数不同。他们之间毫无关系,是不同的函数,可能是功能类似,命名一样是为了增加可读性。
无法以返回值类型作为重载函数的区分标准。

覆盖(方法重写)override,发生在子类中,必须有继承的情况下才有覆盖发生。
继承一个类,也就有了父类的全部方法,改变方法的功能就把那个函数在其子函数中重新实现一遍。这样在调用的时候,就是执行子类中的过程了,父类中的函数就被覆盖了。
如需父类中原有的方法用super关键字引用当前类的父类。
子类的访问修饰符权限权限不能小于父类
重写要求方法名,形参列表相同,返回值相同

方法重载
1.方法名相同
2.在同一个作用域
3.形参列表不同(形参类形不同或者个数不同)
分类
1.成员方法重载
2.构造方法重载

方法重写override,子类重新定义父类方法
子类重写的方法名,形参列表,返回值类型和父类完全一致
子类重写的方法访问的权限不低于父类的访问修饰符权限

覆盖(方法重写)override,发生在子类中,必须有继承的情况下才有覆盖发生。
继承一个类,也就有了父类的全部方法,改变方法的功能就把那个函数在其子函数中重新实现一遍。这样在调用的时候,就是执行子类中的过程了,父类中的函数就被覆盖了。
如需父类中原有的方法用super关键字引用当前类的父类。
优点:
提高了代码的复用性,增加了代码的耦合性
子类的访问修饰符权限权限不能小于父类
重写要求方法名,形参列表相同,返回值相同

什么是继承?
关键字:extends
1.子类又称超类拓展类,父类又称基类
2.类的继承只能是单继承(一个类只能继承一个父类,一个类可由多个类继承)
3.java会给每一个没有设置父类的类,自动添加一个父类,Object。
子类继承了父类的所有属性和方法

继承的好处?
1。提高了代码的复用性
2.让类与类之间产生了关系,提供了另一特征多态的前提
缺点:多层关系类之间的依赖性非常高,增加了耦合性

逻辑与&与短路与&&的区别?
逻辑与&,无论左边表达式是否正确,右侧都会参与计算。可以用作位计算符,当&操作符两边的表达式不是布尔类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低四个bit位。
短路与&&,具有短路的功能,只有左侧表达式为真时,右侧表达式才会参与计算
逻辑与&与短路与&&仅仅两个条件同时为真,结果为真
逻辑或|与短路或||,只要两个条件有一个为真,结果为真
!逻辑为真时,它为假。逻辑为假时,它为真

|与||的区别
1.||(短路或)若前面表达式为真,则直接输出true
逻辑或|,无论左边表达式是否正确,右侧都会参与计算。

.冒泡排序的实现?
1.它重复的走访要排序的数列,一次比较两个数列元素,如果顺序不对则进行交换,并一直重复这样的走访操作,直到没有要交换的数据元素为止
用二重循环实现,外循环变量设为i,内循环变量设为j,假设如果有n个数需要进行排序,则外循环重复n-1次,内循环重复n-1……1次每次进行比较的两个元素都是与内循环j有关的,它们可以分别用a[j],a[j+1]标识,i的值依次为1……n-1,对于每一个i,j的值依次为0……n-1
设数组长度为N
1.比较相邻的前后两个数据,如果前面的数据大于后面的数据,就将两个数据交换。
2.这样对数组的第N个数据进行一次遍历后,最大的一个数据就沉到数组第N-1个位置。
3.N=N-1,如果N不为零就重复前面两部,否则排序完成。
简而言之:冒泡排序 外层循环N-1,内层循环N-1-i

运算符优先顺序
!>算数运算符±*/>比较运算符>,<,>=,<=,!=,>逻辑运算符&&,||,&,|
三元运算符 if-else

遍历集合的几种方式
1.for循环
2.增强for循环(使用泛型)
3.使用Iterator迭代器

嵌套
if语句,多重If多重架构,结构复杂,条件为等值判断
switch(表达式)
case ;常量(固定不变的数据,唯一的);
代码块;
break;(可选的,结束分支语句,跳出switch语句块)

default;(可选的,所有的case值不满足时,就会执行default)
break;
条件表达式(循环条件):迭代表达式(维护计数器),for循环指定循环次数
while循环通常用于循环次数不固定的,仅知道循环结束条件的场合

死循环(不会停止的循环)

for(){}
while(true){}
do{}
while(true);

i%10,i这个数除十取余数

Math.pow(a,3.0D),a的三次方

双等于,前后两个变量值一致,返回true
object常用类是所有类的基类

Java创建对象的方式(四种)?
new
clone()克隆
反射
反序列化

序列化反序列化
实体类实现一个接口Serializable
再javaBean对象中增加serial VersionUID字段,用来固定版本,才能序列化
反序列,与序列化相对,相当于编码和解码的过程,当数据需要跨语言传输时,必须将其转化为一种中间结构,这种中间结构能被双方识别还原,这个过程就是序列化和反序列化
序列化:对象流化,持久化存储,将对象转化成二进制的过程,
把对象存储到本地磁盘或者传递给其它网络节点的过程
反序列化:流化转化为对象,把磁盘中的对象数据或者网络节点中的对象数据,恢复成对象的过程,
把序列化后生成的二进制数据转化为对象的过程

反序列,与序列化相对,相当于编码和解码的过程,当数据需要跨语言传输时,必须将其转化为一种中间结构,这种中间结构能被双方识别还原,这个过程就是序列化和反序列化
序列化对象流化,持久化存储,反序列化流化转化为对象

反射,根据一个已经实例化的对象来还原类的完整信息
在运行中,对于任意一个类,都能过知道这个类的所有属性和方法,任意对象能调用它的属性和方法,改变它的属性

equal与hashcode的区别?
equals():反映的是对象或变量具体的值,可能是对象的引用,也可能是值类型的值。
Hashcode():计算出对象实例的哈希码,并返回哈希码,又称为散列函数。返回对象的内存地址处理后结构(数值)
比较对象一般先用hashcode(),如果哈希值不一样,两个对象肯定不相等
hashcode相同,再去比较equal(),equal也相同,两个对象相同
重写了equal方法也要重新hashcode方法,并且保证equal()方法返回结果为true,hashcode()返回值也相同,则表示两个对象相同。

equal和双等于的区别?
equal方法存储在Object类中(是java.lang.Object类的方法),所有的类都可以重写
equal方法底层依赖双等于操作符
equal和双等于操作符结果是一致的
1.对于字符串变量
双等于比较两个变量本身的值,即两个对象在内存中的首地址。
equals()比较字符串中所包含的内容是否相同。
2.对于非字符串变量
双等于和”equals“方法的作用是相同的都是用来比较其对象在堆内存中的首地址,即比较两个引用变量是否指向同一变量是否指向同一对象。
1.如果是基本类型比较,那么只能用双等于来比较,不能用equals
基本类型的包装类型引用变量,双等于比较地址,equal是比较内容的

String类中使用双等于,比较的是两个字符串对象是否为同一对象,与字符串内容无关
object类中equal方法的底层实现是使用双等于
所有类都可以重写equal方法

String类中重写了equal()方法
equal()比较两个对象的地址值是否相等
String类中重写了equal方法具体实现的是比较两个字符串的内容是否相同,重新更改了object类方法的逻辑

object类
它是所有父类的基类,如果某个没有显示继承一个类,那么这个类的父类是object
由于所有类都继承于object,都可以调用object的toString方法
所有类都可以重写tostring()方法
在输出一个对象时,默认会调用toString()方法
toString()方法返回的是全类名+引用地址

String类是字符串的处理类,它是引用类型
toCharArray()方法,可以将字符串转化为一个字符数据
replace()替换字符串
contains():判断字符串是否包含指定字符,
compare To()比较字符串大小ASCII阿克萨斯码按照字典顺序比较
indexof()返回字符串第一次出现的位置,
lastindexof()返回字符串最后一次出现的位置
substring()截取字符串
length()返回字符串长度
split()根据分隔符字符串转化为数组
trim()去除前后空格
replaceall()替换所有的字符

Index(string s,int index)如果没找到索引则返回-1,结束循环
找到索引key,需要维护计数器,更新索引所在的位置

进程和线程的区别?
1.功能不同:进程是程序在数据集合上的一次运行活动,资源分配和调度的最小单位,操作系统结构的基础。线程是操作系统能够运算调度的最小单位,包含在进程中,是进程中的实际运作单位。
2.工作原理不同:早期进程是程序的基本执行实体,当代,进程是线程的容器。程序是指令数据及其组织形式的描述,进程是程序的实体。线程是独立调度和分派的基本单位。线程分为操作系统内核调度内核线程,由用户进程自行调度的用户进程,或者由内核与用户进程,进行混合调度。
3.作用不同:进程是操作系统的最基本,最重要的概念,多道程序设计操作系统都建立在进程的基础上。一个进程可以包含多个线程

进程和线程的关系
一个程序至少有一个进程,一个进程至少有一个线程
线程的划分尺度小于进程,使得多线程的并发现高
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,提供了程序运行效率
每个独立的线程都有一个程序入口,但是线程不能过独立运行,必须依赖于进程

进程:是系统进行资源分配和调度的基本单位,有自己的生命周期
线程:是程序中一个单一的执行路径或者控制流程

多线程,在单个程序里同时运行多个线程完成不同的工作
当用户发起请求,服务器收到请求后处理所有的业务逻辑返回的结果就是一个线程
当客户端多个请求同时请求服务器,这就是多线程(并发)
多个处理器同时处理多个不同的任务,多个处理器或者多台机器同时处理一段逻辑,(并行)

使用多线程的原因?
提升CPU的计算能力,避免资源浪费
提升系统响应速度

共享
允许不同的线程访问资源
共享资源是多线程允许不止一个线程访问类变量或者实例变量
创建多线程的方法

创建多线程的方式?
一继承Thread
创建一个子类继承于Thread类
重写run()方法
创建子类对象
启动线程使用star()方法

二创建一个实现runnable接口类
重写runnable接口的run方法
创建一个Runnable接口实现类的对象
将子类对象作为形参传递给Thread类的构造器

thread中star()和run()的区别?
star用来启动线程,此线程处于就绪状态,并没有运行,真正实现了多线程运行。
run此线程真正运行

优点
实现的方式避免了Java单继承的局限性
多个线程要操作同一个共享资源,更适合使用实现的方式
使用实现的方式引发的问题(此线程存在安全问题)
由于一个线程在操作共享数据的过程中,未执行完毕,另外的子线程此时参与过来,导致共享线程出错

什么是死锁?
两个或多个线程的相互等待,导致线程都无法执行,叫做线程死锁。

死锁产生的四个必要条件
1.互斥条件:一个资源只能被一个线程占用
2.不剥夺条件:进程使用的资源在未完成之前,不能被其他进程剥夺
3.请求和保持条件:一个进程因为请求资源而阻塞时,对已经获得资源保持不放
4.循环等待条件:若干进程形成了一种头尾相接环状等待资源的关系

如何解决线程问题
必须让一个线程操作共享数据完毕后,其它线程才有机会参与共享数据操作
Java实现多线程安全使用的是线程的同步机制
局部变量
1.同步代码
synchronized(同步监视器)
需要同步的代码块(共享的数据代码)
共享数据:多个线程共同操作的同一数据或者资源(成员变量或类变量)
同步监视器(锁)通常使用一个对象(任何对象)来充当,那个线程获取此监视器,就可以执行同步代码(要求所有的线程共用一把锁)
2.同步方法
将操作数据共享的方法声明成synchronized
保证当一个子线程执行到此方法时,其它子线程排队等候直到该线程执行完方法
如果使用继承的方式创建多线程
不能使用this充当同步监视器,因为this代表不同对象
可以创建一个static类型的对象

并行和并发?
并发又称共行性,处理多个同时活动的能力
并行是指同时发生的两个并发事件
并行同时多个处理器处理一个任务
并发一个处理器处理多个任务

线程分类
1.守护线程(daemon thread)是指在后台运行的线程,用于提供后台服务
2.用户线程(user thread)创建线程的默认线程
当进程在还有用户线程在运行时,进程不终止、
当进程只有守护线程时进程终止

线程生命周期
新建(new)->就绪(runnable)->运行->(running)->阻塞(blocked)->死亡(dead)

super
super可以通过子类构造器调用父类构造器,
当创建子类对象时,会调用父类的无参构造器super(),默认调用
super可以调用父类的非私有方法
当super和this同时存在时,一定要先使用super调用父类构造器,初始化父类成员属性,再用this初始化子类的成员属性

This和super关键字的区别?
1.this代表本类对应用的引用
2.super代表父类存储空间的标识(父类引用可以操作父类的成员)

向上转型:父类的引用指向子类的实例
编译时调用时的父类的方法,执行的是子类的方法
编译时看左边,运行时看右边

上转型:子类对象交给父类引用,可以自动转化
下转型:强制类型转换

final
final修饰的是不能被继承的
修饰成员属性是常量(不能被赋值)
不能被重写
常量储存在常量区的常量池

finally的作用?
处理Java后续工作
1.必须使用在catch的最后位置
2.必须执行,无条件执行

命名规则,全部大写,如果有多个单词中间使用下划线隔开
static 修饰成员变量(类变量)
它是随着类的加载而加载,类变量只保留一次
访问变量名:通过类名,属性名访问
应用场景:一般在工具类中将方法声明成静态方法
静态方法不能以任何方式引用this关键字
抽象类中可以包含抽象方法也可以包含非抽象方法,不能被实例化,只能被继承,普通类中不能定义抽象方法
有抽象方法的类一定是抽象类
集合:看作一种容器,用来存储对象,所有的集合都位于Java。util包下

数组和集合的区别?
数组存储相同的数据类型,集合可以存储不同的数据类型
数组可以存储基本数据类型,也可以存储对象,集合只能存储对象
数组长度是不可变的,一旦确定了数组的长度,数组中只能存储固定个数的元素
集合可以存储数量不确定的数据

包含的主要接口
collection
list:有序,可重复
ArrayList:主要实现类
linklist:链表的实现方式,主要对于频繁插入,删除操作
vector:古老的实现类
set无序,不可重复
queue队列
map

共享资源
1.允许被不同线程访问的资源
2.共享资源时多线程允许被不只一个线程访问的类变量(静态变量),或者实例变量


1.当多个线程共同使用共享资源时,出现资源争抢
一个资源可以被多个线程中对象访问,不会出现冲突,这就是线程安全
造成线程不安全的因素
存在多个线程同时修改一个共享资源

避免方法,
1使用局部变量,
2尽量不做修改共享资源的操作
3对共享资源加锁

StringBuffer和StringBuilder
StringBuffer:就是字符串缓冲区,用于存储可变字符序列的容器
允许对字符串修改,长度可变,线程安全,效率低
StringBuilder:不可变字符串,线程不安全,效率高

StringBuffer
构造

StringBuffer(),StringBuffer(int size),StringBuffer(String str)

添加

StringBuffer append(date),StringBuffer insert(index.data)

删除
包含头,不包含尾

StringBuffer delete(start.end)

删除指定位置元素

StringBuffer deleteCharAt(int index)

查找

char charAt(index),int indexOf(string),int lastIndexOf(string)

修改

StringBuffer replace(star,end,string),void setCharAt(index,char)

StringBuffer和StringBuilder区别?
1.线程安全
StringBuffer:线程安全
StringBuilder:线程不安全
2.缓冲区
StringBuffer每次获取toString都会直接使用缓冲区的值来构造一个字符串。
StringBuiler每次都需要复制一次字符组,在构造一次字符串。
3.性能
StringBuffer是线程安全的,它所有的公开方法都是同步的,StringBuilder是没有对方法加锁同步的。StringBuilder的性能远大于StringBuffer。

为什么使用buffered?
缓存特定文件的输入

包装类:对基本数据类型做封装,解决了基本数据变量不能充当对象使用的问题

单例表单的强转之int类型
int–>Integer

List<Integer>list = new ArrayList<>()

日期类
Data 年-月-日 时:分:秒
Simple Data Format 年/月/日 日期格式化,可以指定多种格式
Calendar 月/日

生成随机数
Math.random():生成随机数 0.0-1.0之间
Random类
nextInt():生成随机数
获取指定区间的随机数
param min 最小值
param max 最大值

API 应用程序访问接口
集合:看作一种容器,用来存储对象信息,所有的集都位于java.util包下

什么是函数编程?
函数式编程是种编程典范,它将电脑运算视为函数的计算

关于lambda表达式的理解?
一个参数param=>expr
多个参数(param-list)=>expr

什么是编译时异常和运行时异常?
编译时异常,一般是语法上存在问题
运行异常,是指程序在运行中出现错误

处理异常的方式?
1.对代码块用try…catch进行异常捕获
2.在该代码的方法体外用throws进行抛出声明
3.在代码块用throw手动抛出一个异常对象

throw与throws的区别?
1.throw代表动作,表示抛出一个异常动作。throws代表一种状态,代表方法可能有异常抛出。
2.throw用在方法实现中,throws用在方法声明中。
3.throw只可处理一条数据,throws可处理多条数据

Io流是一种有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象,数据在两设备之间的传输称为流

io流的分类?
根据数据流向分为
输入流InputStream,输出流outputstream
输入流readed(只读),输出流writer(编写)
根据处理数据类型的不同分为
字节流以type字节(8bit)为单位,
字符流以char为单位,
节点流:直接作用于文件,或直接与数据相连,FileInputStream,将file作位形参传递给构造器
处理流:加速文件的读写操作,在节点流上面接了一层,BufferedInputStream
关闭流out.writer(bytes,off:0,len);
1.节点流,直接从指定的位置读或写
2.过滤器,其他的流

字节流和字符流的区别?
字节流一次八个二进制(一个字节,八个字符),字符流十六个二进制,(两个字节)
字节流处理音频视频图像文本,字符流主要 处理文本
字节流不会用到缓冲区(对文件本身直接操作),字符流会用到缓冲区(通过缓冲区操作文件)

优先选用字节流,硬盘上的所有文件都是以字节的形式进行存储或保存的,包括图片等,但是字符只能在内存中才会形成。

硬盘和内存的区别?
硬盘属于外部存储设备(”外存“),内存属于内部存储设备,外部存储设备的数据只有调入内存中才能真正使用(运行),硬盘相当于一个数据库,可以存储操作系统,软件文件,(存储暂时不用的信息,磁性材料制成的,信息可以长期保存)硬盘分为机械硬盘(普通硬盘,便宜,空间的,有噪音),固态硬盘(类似于U盘,采用集成电路存储,由控制单元存储单元组成,无噪音,性能好)

内存又称为主存,分为随机存储器(RAM),只读存储器(ROM),高速缓存(CACHE),是半导体材料制成的,信息会随着断电消失。
CPU与硬盘不发生直接的数据交换,CPU通过控制信号(指令)指挥硬盘工作
编写的Java代码,保存至硬盘,要执行代码,需要把代码从硬盘中读取到内存中(分为数据和指令(数据执行的说明)),代码变为二进制文件存储至内存,继续执行代码操作CPU(读写速度快)收到代码中的指令,去内存中读取将要用到的数据,存到自己的寄存器中由CPU中的运算器执行运算,执行下一条命令,结果保存至寄存器中,之前的数据被覆盖,CPU和内存一起完成了一次运算,这个文件就被称为源文件,寄存器(存储部件,容量有限,能存储的数据大小,32(四个字节)或64(八个字节)),运算器(计算的核心,无法直接操作内存中的数据,运算器操作的是寄存器中的数据)

一台计算机包含以下五个部分
运算器,控制器,存储器(保存信息,内部存储器(内存,内存地址,存储的数据都是二进制的,),外部存储器(磁盘(硬盘(固态硬盘,传统机械硬盘),软盘)),输入设备,输出设备,

集合包括的主要接口:

1.Collection接口:
Collections:操作集合的工具类

1.List接口(Collection接口的子接口):存储有序的,可以重复的元素,存储和取出元素的顺序一致(底层实现是使用的数组)
reverses(List):反转List集合中的元素
Collections.reverses(list);
System.out.println(list);
shuffle(List):对list集合元素进行随机排序
sort(List):根据元素的自然顺序对指定集合按照升序排序
swap(List,int,int);将指定集合中索引为i和索引为j的元素进行交换
有索引,包含了一些带索引的方法(底层实现是使用数组,可变数组)

常用方法
void add(int index,Object ele):
在指定索引位置添加元素
boolean addAll(int index,Collection eles)
在指定的索引位置添加一个集合
Object get(int index)
获取指定索引位置的元素
int indexOf(Object obj)
返回obj在集合中首次出现的索引位置,如果没找到索引,则返回-1
int lastIndexOf(Object obj)
返回obj在集合中最后一次出现的索引位置,如果没找到索引,则返回-1
Object remove(int index)
删除指定索引位置的元素
Object set(int index,Object ele)
设置指定索引位置的元素(update)

List集合注意事项

//没有分配具体实例
List list1 =null;
//分配了具体实例,但是集合中没有任何元素
List list2 =new ArrayList();
//由于没有分配具体实例,list1引用找不到对象实例,会报一个NullPointerException(空指针异常)
System.out.println(list1.size());
System.out.println(list2);
System.out.println(list2.size());
//在遍历集合之前,要先判断该集合是否为null且集合中是否有元素
if(list2!=null&&list2.size()!=0){
	for(int i=0; i<list2.size();i++){
System.out.println(list2.get(i));
	}
}

List集合中常用的实现类
–ArrayList主要实现类
底层实现是使用数组的方式来实现(动态数组),允许包含所有元素类型(null)
可以根据索引位置对集合进行快速的随机访问(优点)
向指定索引的位置插入元素或者删除元素速度比较慢(缺点)
–LinkList:双向链表的实现方式,主要对于频繁的插入删除操作,查找指定位置数据的效率高(优点)
使用链表的形式操作数据,访问数据的速度比较慢(缺点)
–Vector(用的少):古老的实现类,底层实现也是数组形式,线程安全,效率较低

ArrayList和LinkList的区别?(考点)
1.ArrayList是基于索引的数据接口,它的底层是数组。
LinkList是以元素列表的形式存储它的数据,使用双向链表的数据结构,每一个元素都和它的前一个和后一个元素链接在一起,这是两种技术,决定不了通过的应用场景

2.频繁的添加和删除操作中,相对于arraylist,linkedlist的添加和删除速度更快
对于随机访问get和set,ArrayList优先于LinkedList因为ArrayList要移动数据。

3.linkedlist比arraylist更占内存。linkedlist为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素
4.对于随机访问get,set,ArrayList优于LinkedList,因为LInkedLIst要移动指针
5.对于频繁的新增和删除工作(Add,Remove)LinkList优先于ArrayList,因为ArrayList要移动数据
List没有分配具体实例,list1找不到引用对象的实例,会报一个NullPointerException(空指针异常)
在遍历集合之前,通常要判断该集合是否为Null且集合中是否有元素

2.Set接口(Collection的子接口):存储无序的(不代表乱序,内部有序,外部无序),不可重复的数据(添加相同的元素只能存储一份)
添加进Set中的元素一定要重写equals和hashcode方法
Set 中的元素存储使用哈希算法,当向Set添加元素时,首先会调用该对象所在的类hashCode方法,计算哈希值,这个哈希值就决定了Set元素的存储位置。再通过equals()方法比较两个对象是否相同,如果相同,则后面的对象不能添加

实现类
–HashSet;set接口的主要的实现类
HashSet是采用哈希算法存储集合的元素,因此有很多存储和查询的性能(底层数据结构是哈希表)
哈希表:综合数组和链表的优点(一个链表的数组)
HashSet不能保证元素的数据排列顺序和添加的顺序一致
内部存储机制;HashSet集合判断两个元素的标准是两个对象通过equal方法比较相等,并且两个对象的hashcode值也相等,从而确保数据的唯一性

为什么不使用数组而使用hashset?
hashset通过哈希值来确定存储位置,可以自由的增加长度,并根据哈希值访问元素,不能挨个遍历索引访问

–LinkedHashSet它是HashSet的一个子类,具有HashSet的特性,是根据元素的Hashcode值来决定元素的存储位置,它也使用链表来维护元素的顺序,输出元素时元素顺序和输出元素顺序一致(性能是低于HashSet)
–TreeSet:它是Sorted Set接口的实现类,可以保证元素处于排序状态(默认是采用自然排序)
TreeSet:内部是二叉树,默认是从小到大排序
自然排序(默认方法):TreeSet会调用集合元素的compareTo(object)方法比较元素的大小关系,然后将元素按照升序排序
定制排序

HashSet和LinkedSet区别?
hashset
1.不能保证元素的排列顺序,顺序有可能发生变化
2.不是同步
3.集合元素可以是null,但只能放一个null
LinkedSet根据元素的hashcode值来决定元素的存储位置,但是它同时使用链表维护元素次序。
使用迭代访问Set元素时性能更好。

List和Set区别?
List和Set都是Collection的子接口
List中提供索引的方式来添加获取元素,而set并不提供
List是存储有序的(key),可以重复的数据
Set是存储无序的,不可重复的数据
底层存储机制不同

list,set,map的区别?
list,set,map分别继承了ArrayList,hashset,hashmap
list允许重复,set不允许重复,map是键值对的形式,key-value key不能重复
Array List线程不安全,底层用的是object数组,Array List对于添加删除响应时间长,查询可通过序列快速定位,Array List会在list尾部预留一定容量的空间,
Array List可以使用增强for循环,线程不安全
hashset底层基于hashmap实现的,set是hashset接口,放入set中的数据不能重复,(因为放入hashset中的数据会先计算hashcode值,来判断插入位置,同时和已经存在set中的数据作hashcode对比,如果有重复的会调用equal方法检查hashcode值相等的对象是否内容相等,如果相等,则不能插入)
hashmap底层是数组和链表的结构,通过key的hashcode值确定value放置的位置,添加用put方法

–TreeSet
2.Queue(队列)
1.Map接口(它和Collection接口是一个平行关系,用于保存具有映射关系的数据):存储的数据是键值对<key,value>就是一个Entry,set存放,不可重复,(Map中保存着两组值,一组是key,一组是value),向map中添加元素时,会调用Key所在类的equals()方法,判断两个key是否相同,如果相同,则添加后面的元素

Map遍历
key;Map是不可重复的,使用set存储(底层实现)(遍历集合)(当向集合中添加相同的元素key时,保留的是后面的元素)
value:Map是可以重复的,使用collection(List)来存储(底层实现)(遍历集合)
一个键值对<key,value>就是一个Entry,Entry是使用set存放的,不可重复的
当向Map中添加元素时,就会调用key所在的类equals()方法,判断两个key是否相同,如果相同则添加后面的的元素

entrySet()遍历key-value (Entry)
1.get(key)方法得到相应的value值,
2.通过entry调用getKey()方法得到key值,
3.通过for each 方法(jdk1.8新特性)
Map实际上是提供了一个Entry内部类里封装key-value(entrySet(),遍历key-value(Entry))

Map集合的优点
类似于字典一样通过key找到对应的value,使这种映射关系方便查找数据
内部类 Map.Entry
Map中包含一个内部类Entry,它封装了一个键值对
常用方法–getKet():获取Entry中包含的value值

Map中常用的方法
Object put(Object key,Object value)
添加元素|更新元素(当向集合中添加的元素key相同时,保留的是后面的元素)
Object remove(Object key)
移除元素,删除一个key-value
void putAll(Map t)
void clear()
清空元素
Object get(Object key)
获得指定的value如果没找到对应的key,则返回-1
boolean containsKey(Object key)
是否包含指定的key
boolean containsValue(Object Value)
是否包含指定的value
int size()
集合的长度
boolean isEmpty()
是否为空
boolean equals(Object obj)
Set keySet()
返回map所有key组成的集合Set
Collection values()
返回map所有value组成的集合Collection
Set entrySet()
返回map所有键值对组成的集合Set(每一个集合都是一个Entry对象)

内部类map,entry
map中包含一个内部类entry,它封装了一个键值对
常用方法
getkey()
获取entry中包含的key值
getvalue()
获取entry中包含的value值

Collection:接口
Collections:操作集合的工具类

reverse(List)反转List集合中的元素
shuffle(List) 对List集合中的元素进行随机排序
sort(List)根据元素的自然顺序对指定集合按照升序排序
swap(List,int,int)将指定集合中索引为i的元素和索引为j的元素进行交换

在没有使用泛型的时候任何object,及其子类对象都可以添加
在强制转换成int类型时,会引发类型转换异常:ClassCastException异常

Map实现类
Map<key,value>map=new HashMap<key,value>();
–HashMap:主要的实现类
–LinkedHashMap:使用链表的方式来添加Map元素的顺序(迭代顺序和插入顺序一致)
–TreeMap
–Hashtable子类,线程安全的,不建议使用,不允许使用null作为key,value
Properties:,通常来处理属性文件,键值对都是String类型)
addAll(Collection coll)将集合中的所有元素添加到当前集合
Arrays:操作数组的一个工具
isEmpty():判断该集合是否为空,空为true
clear()清空集合元素
contains(Object obj):判断集合中是否可以包含指定元素
如果存入集合的元素是自定义对象,需要重写hashcode和equals方法
remove(Object obj)删除集合中的元素
removeAll(Collection coll):从当前集合中删除另外一个集合
toArray()将集合转化为数组
iterator()迭代器,可以实现对集合的遍历(迭代器是一种设计模式,它是一个轻量级对象)
Iterator是一个接口,是集合的迭代器,集合可以通过Iterator去遍历集合的元素
hasNext():判断集合中四否存在下一个元素,如果有则返回true
next():返回集合了的下一个元素

Hash Map和Hash table的主要区别?
-Hashtable:子类,线程安全的,不建议使用,不允许使用null作为key,value (Properties:键值对都是String类型)
线程安全性,速度
hashmap是非线程的可以接受null,hashtable是线程的不允许使用null作为key,value

遍历集合:
1.使用迭代器Iterator实现集合的遍历
2.使用增强for 循环实现集合遍历(底层实现是使用迭代器)
3.使用for 循环
4.将集合转化为数组(toArray),在进行遍历

泛型:
JDK1.5出现的安全机制
避免强制类型转化引发异常
限制了数据类型,保护了数据类型安全
将运行期间引发的异常赚到了编译期间

什么时候使用泛型?
1.当操作的引用类型不确定的时候,<T|E>
2.其中<>就是一个用于接收具体数据类型的代表(明确传入的具体引用数据类型)

泛型的好处?
同时具备可重用性类型安全和效率

使用泛型执行的流程?
在编译时,通过<>可以确保类型的安全,在运行时将泛型移除,,因为了兼容运行时类的加载器(ClassLoader)

泛型类定义和声明/?
在类名后通过<>指定一个或多个类型参数,同时还可以对类型参数取值范围进行限制,多个类型之间用,隔开 例如: public class Person<T,E>
默认类型object类型
当实例化泛型对象,指定泛型的类型,指定后对应的数据使用泛型的位置就已经确定为实例化中指定的类型
如果自定义了泛型类,但是在实例化的时候没有使用,那么默认类型都是object类型

泛型方法
在方法访问修饰符后通过<>指定方形方法的类型参数
泛型方法定义和所在的类是不是泛型无关

通配符
1.?
2.? extend A (向下限定)子转父
3.? super A (向上限定)父转子

Comparable接口
位于Java.lang 包下
实现原理基于红黑二叉树
包含一个比较方法compareTo(T t)
字符串,根据字典顺序进行比较
自定义类型需要实现Comparable接口,重写compareTo()方法,实现自定义排序规则
分析String类中的compareTo()方法和equals()方法
Comparator接口
是一个排序比较器,位于java.util包下
包含一个比较的方法compare(T t1,T t2)
如果一个类实现这个接口,一定要重写compare方法,但不一定要实现equals方法

比较方法 compare(T t1,T t2)
如果一个类实现这个接口,一定要重写compare方法,但不一定会实现equals()方法

使用匿名实现类
提供实现类的对象
使用lambda表达式

Comparable接口和Comparator接口区别?
排序规则实现的方法不同
Comparable接口一个通用接口可以通过它实现自己特定比较
,Comparator接口可以看成一种算法的实现,在需要容器集合比较功能的时侯,来指定这个比较器,也可以看成一种设计模式(将算法与数据分离)

接口的默认方法
在接口中添加一个非抽象类使用default关键字
我们把这个非抽象方法理解成一个扩展方法

函数式编程(一切皆函数)(面向对象:一切皆对象 )
将处理问题的粒度从类变成函数,从而可以更好的满足系统对重用性和扩展性的支持
可以将函数作位参数传递给另一个函数
简化代码操作,函数运行的结果只依赖于输入的参数
开发速度较快,易于并发编程,不需要考虑死锁(dead lock)
函数式编程比较耗费CPU资源,学习速度高,代码维护性比较差

lambda表达式
一种新的语法形式,简化了开发的编程操作,由编译器转化为常规的代码
函数式编程的体现方式
允许通过表达式代替功能接口,就类似于匿名方法(有参数列表和代码块)
语法:->成为lambda表达式操作符
结构(parameters)->expression|{statements};
左侧参数列表,右侧lambda表达式需要执行的代码块(主体结构)

lambda表达式应用场景
使用内部迭代取代外部迭代
外部迭代:描述怎么干,只能顺序处理List集合中的数据
内部迭代:描述干什么,而不是怎么干,不一定要处理list元素,使用for each
使用流水线的方式处理数据:使用Stream Stream对集合的包装,通常和lambda表达式一起用
支持很多操作:filter,limit,sorted,max,min,collect,sum,map
框架保存类
相对路径:在当前文件目录下的文件路径
绝对路径:包含盘符在内的完整路径

exists()判断是否存在
canWrite()是否可写
canRead()是否可读
isFile()是否为文件
createewfile()新建文件
delete()删除
isDirectory()是否为目录
length()文件的长度
lastModify()最后一次修改时间
flush()清空缓冲区数据,但是并没有关闭流,刷新之后还可以继续使用液对象进行数据操作
close()关闭液,在关闭流之前,先刷新,关闭之后流对象不能再被使用
Thread类的常用方法
star():启动线程并执行run()方法
run():子线程需要执行的代码放入run()方法中
currentThread()获取当前线程
getName():获取子线程名称
setName():设置子线程名称
yield():调用此方法的线程释放cpu的执行权
join():在子线程一中调用线程二的join()方法,表示执行此方法时,线程一停止执行,直到线程二执行完成后
sleep(long 1):1s=1000ms 让当前线程睡眠
isAlive():判断当前线程是否存活
优先级
getPriority():获取优先级
setPriority():设置改变优先级
线程通信的方法:
wait():等待:调用此方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被唤醒
notify():唤醒等待的线程;可以唤醒等待队列中第一个等待用以共享资源的线程,并使该线程退出等待序列,进入可运行状态
notify():唤醒所有等待的线程;可以使所有正在等待队列中同一共享资源的线程退出等待状态,进入可运行状态

war包和jar包的区别
jar包就是别人已经写好的一些类,然后对这些类进行打包。可以将这些jar包引入到你的项目中,可以直接使用这些jar包中的类和属性,这些jar包一般放在lib目录下。
war包是JavaWeb程序打的包,war包里面包括写的代码编译成的class文件,依赖的包,配置文件,所有的网站页面,包括html,jsp等等。一个war包可以理解为是一个web项目,里面是项目的所有东西。
WAR文件代表了一个Web应用程序,JAR是类的归档文件。

同时启动两个tomcat要修改哪些
修改http访问端口,将8080修改为tomcat不在使用的端口号
修改其中一个tomcat的Shutdown端口
修改其中一个tomcat的8009端口
依次启动两个tomcat

三元运算符
三元运算符是软件编程中的一个固定格式,语法是“条件表达式?表达式1:表达式2”。使用这个算法可以使调用数据时逐级筛选。
若条件式的值为true,则整个表达式取值1,否则取值2
表达式:“()? :”。
()中进行二元运算
?再运算,就形成三元运算符

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值