资讯详情

Java知识点概要

Java知识点

一、java和Scala

1、scala声明变量的方法有多少?

  • 1)scala变量分为:不可变量 和 可变变量
    • val:定义不可重新赋值的变量(值不可修改),使用val声明变量,相当于java 中的final修改不能指向其他数据
    • var:定义可重新赋值的变量(值可修改),后期可修改重新赋值
  • 2)scala声明变量为:变量名称 在前,,跟java是正好相反
  • 3)scala中定义变量不能写类型,让scala自动推断编译器

2、scala与Java的区别

scala是运行在 JVM 支持面向对象和面向函数编程的多范式编程语言,scala最后,它被编译成.class运行在文件中JVM其实虚拟机本质上还是java, 所以在scala和java可以互相调整api,兼容Java,可访问庞大的Java类库。

  • Scala它是函数和面向对象编程的结合,Java是面向对象的编程语言。

  • 用Scala编写的代码更短更紧凑。Java代码是长格式的。

  • (1)

    • scala声明变量,名称在前,类型在后,java正好相反;
    • scala定义变量不能写类型,自动推断,句子最后不需要分号;
    • scala中val声明不可变量相当于final,用var 声明可变量;
    • scala用关键字lazy来定义惰性变量,调用时,才实例化;
    • scala大写字母开头用于所有类型的整形手术Int而不是Integer
  • (2)

    • scala通过def 通过语句定义法val 语句定义函数。函数没有返回值Unit,相当于java的void 。
    • scala的return可选,方法调用会自动返回最终求值的表达式。scala使用了return需要显示指定方法的返回值
  • (3)

    • scala不支持接口interface,采用trait(类似于Java抽象类)。 java支持接口
    • 修饰符的默认值 scala默认是public,java默认是protected.
  • (4)对的支持 :scala采用三个双引号“”“支持换行字符串,Java需要采用“ 连接字符串。

3、Scala方法函数

  • 1、def 定义方法,参数列表的类型不可节省,返回类型自动推断可节省(递归方法除外), 最后一行不写返回值。return ;
  • 2、val函数是一个对象(变量),不需要返回类型
  • 3.方法是类的一部分,属于类或对象,运行时加载到 JVM 的方法区;
  • 4.函数是一个完整的对象,可以赋值变量,运行时加载到 JVM堆内存中。函数对象有apply,curried,toString,tupled没有继承这些方法。 Trait(Trait(特征) 相当于 Java 的接口。
  • 5方法转换为函数,val a = add _

方法 描述

  • 遍历 : 函数输入为集合元素,返回为空的函数对象。list.foreach(println)
  • 映射 :函数输入是一种类型A,返回为类型B。list.map(_*10)
  • 扁平化映射 :将函数输入到一个函数对象中合元素,并返回到集合元素 list.flatMap(_.split(" "))
  • 过滤 : 输入函数对象,接收集合参数,返回布尔类型
  • 排序 :输入函数对象,接收集合元素参数,返回排序列表
  • 分组 : 输入函数对象,接收集合元素类型的参数,返回K类型key,这个key它将用于分组,相同key放在一组中
  • 聚合 :第一个用于连续聚合的函数对象传输A1类型参数是当前聚合后的变量,第二个A1类型参数为:当前聚合元素,列表最终聚合为元素 // 第一个下划线表示第一个参数,即历史的聚合数据结果 // 第二个下划线表示第二个参数,即当前要聚合的数据元素 scala> a.reduce(_ _)

4.方法和函数的区别?

:val 语句 定义函数;def 语句 定义方法。

  • 方法是类的一部分,属于类或对象。运行时加载到 JVM 的方法区。Scala 中的方法跟 Java 方法是组成类的一部分。
  • 函数是一个完整的对象,可以完整对象。运行时加载 JVM堆内存中。函数对象有apply,curried,toString,tupled这些方法方法。
  • Scala 其实中函数是继承的 Trait(Trait(特征) 相当于 Java 事实上,它比接口更强大。
  • 换句话说,在类中定义的函数是方法。方法转换为函数:使用_可以将方法转换为函数,作为变量传递,需要将方法转换为函数

//定义方法 scala> def m1(x: Int) = x   1 m1: (x: Int)Int  #方法是一个def一个带有参数列表(无参数列表)的逻辑操块, #这正如object或者class成员的方法是一样的。(上面有定义说明)  //函数的定义 scala> val f1 = (x : Int) => x   1 f1: span class="token builtin">Int => Int = $$Lambda$1036/961708482@1573e8a5
​
#函数是一个赋值给一个变量(或者常量)的匿名方法(带或者不带参数列表),
#并且,通过 =>转换符号 跟上逻辑代码块的一个表达式。
# =>转换符号 后面的逻辑代码块的写法与method的body部分相同。

scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int
​
scala> val a = add _
a: (Int, Int) => Int = <function2>

5、集合

·(1),val a = (1, “张三”, 20, “北京市”) :可包含一组不同类型的值,_1表 示访问第一个元素

·(2),scala.collection.mutable.ArrayBuffer:增+=、删-=、追加++=, array.sum/max/min/sorted

· (3),scala.collection.mutable.Map: 增map+=(“w” ->35),删map -=“w”,改map(“li”)=50,查map(“zh”)

·(4),scala.collection.mutable.Set:不重复 无顺序,增+=、删-=、追 加++=,

·(5),scala.collection.mutable.ListBuffer,可重复 有顺序,增+=、删 -=、++=加list,

Scala元组将固定数量的项目组合在一起,以便它们可以作为一个整体传递。 元组可以容纳不同类型的对象( 与数组或列表不同),但它们也是不可变类型。

6、匿名函数:一个没有名称的函数

//定义一个数组
scala> val array=Array(1,2,3,4,5)
array: Array[Int] = Array(1, 2, 3, 4, 5)
​
//定义一个没有名称的函数----匿名函数
scala> array.map(x=>x*10)
res1: Array[Int] = Array(10, 20, 30, 40, 50)

7、柯里化

含义:方法可以定义多个参数列表,。这被称为柯里化。

  • 柯里化(Currying)是一种,将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

  • 柯里化,是把接受多个参数的函数,变换成,接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

  • 柯里化,是函数式编程的一个重要概念。它既能减少代码冗余,也能增加可读性。另外,附带着还能用来装逼。

curry化最大的意义在于, ,这样所有的函数就都统一了,方便做lambda演算。

在scala里,curry化对类型推演也有帮助,scala的类型推演是局部的,在同一个参数列表中后面的参数不能借助前面的参数类型进行推演,curry化以后,放在两个参数列表里,后面一个参数列表里的参数可以借助前面一个参数列表里的参数类型进行推演。这就是为什么 foldLeft这种函数的定义都是curry的形式

# 定义2个整数相乘运算
def multiplie2par(x:Int,y:Int)=x*y
​
# 使用柯里化技术,
# 将上述2个整数的乘法函数,改修为接受一个参数的函数,
# 该函数 返回 是一个以原有第二个参数为参数的函数。
​
def multiplie1par(x:Int)=(y:Int)=>x*y
​
# 说明:
# multiplie1par(x:Int) 为接收一个参数的新等价函数,
# (y:Int)=>x*y 则是新等价函数的返回体,它本身就是一个函数(严格来说应该是一个匿名函数),
# 参数为 除等价新函数的参数外原函数剩余的参数。
​
进一步简化为:
def multiplie1par1(x:Int)(y:Int)=x*y
​
    
三个整数乘法的函数
def multiplie3par(x:Int,y:Int,z:Int)=x*y*z
def multiplie3par1(x:Int)=(y:Int,z:Int)=>x*y*z
def multiplie3par2(x:Int)(y:Int)(z:Int)=x*y*z
def multiplie3par3(x:Int)(y:Int)=(z:Int)=>x*y*z
​
# 编译执行的结果都是一样,调用不同形式参数过程略有不同,
# 直接参入三个参数的一步到位就可以得到运算结果,而
# 传入1或者2个参数的需要分步骤再传入第2/3或者第3个参数才能求出三个整数相乘的结果,
# 很好地体现了延迟执行或者固定易变因素等方面能力。
​
def getAddress(a:String):(String,String)=>String={ 
        
       (b:String,c:String)=>a+"-"+b+"-"+c
       }
​
​
scala> val f1=getAddress("china")
f1: (String, String) => String = <function2>
​
scala> f1("beijing","tiananmen")
res5: String = china-beijing-tiananmen
​
​
​
//这里就可以这样去定义方法
​
def getAddress(a:String)(b:String,c:String):String={ 
         
        a+"-"+b+"-"+c 
        }
//调用
scala> getAddress("china")("beijing","tiananmen")
res0: String = china-beijing-tiananmen
​
//之前学习使用的下面这些操作就是使用到了柯里化
List(1,2,3,4).fold(0)(_+_)
List(1,2,3,4).foldLeft(0)(_+_)
List(1,2,3,4).foldRight(0)(_+_)

8、闭包

var factor=10
​
val f1=(x:Int) => x*factor
​
//定义的函数f1,它的返回值是依赖于不在函数作用域的一个变量
​
//后期必须要要获取到这个变量才能执行
//spark和flink程序的开发中大量的使用到函数,函数的返回值依赖的变量可能都需要进行大量的网络传输获取得到。
//这里就需要这些变量实现序列化进行网络传输。

scala中是没有Java中的静态成员的。如果将来我们需要用到static变量、static方法,就要用到scala中的单例对象object

7、守卫

scala> for(i <- 1 to 10 if i >5) println(i) 6 7 8 9 10

8、隐士转换

Scala提供的功能,是Java等编程语言所没有的功能。 scala允许开发人员自定义类型转换规则,将两个无关的类型通过编程手段让他们自动转换。

隐式转换:在 Scala 编译器进行时,如果找不到合适的类型就会编译失败,此时会在当前的环境中自动推导出合适的类型,从而完成编译。

核心:就是定义一个使用 implicit 关键字修饰的方法 ,实现把一个原始类转换成目标类,进而可以调用目标类中的方法。

作用:简化编程,调用方法时,不需要向隐式参数传参,Scala 会自动在其作用域范围内寻找隐式值,并自动传入。通过隐式转换,可以在不改变代码的情况下,扩展某个类的功能。

隐式函数:使用implicit关键字声明的函数称之为隐式函数

object ScalaImplicit { 
        
    def main(args: Array[String]): Unit = { 
        
      //定义隐式函数 让Double 类型的变量自动转换为int类型
      implicit def transform( d : Double ): Int = { 
        
          d.toInt
      }
      var d : Double = 2.0
      val i : Int = d
      println(i)
    }
}
 

隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数, 此时Scala会尝试找到一个指定类型的用implicit修饰的参数,即隐式值,并注入参数。 所有的隐式转换和隐式参数必须定义在一个object中

object ImplicitConversion { 
        
  def main(args: Array[String]): Unit = { 
        
    //隐式值/变量
    implicit val dd : Double = 2.0

    //隐式参数
    def transform( implicit  d : Double = 3.0 ) = { 
        
      d.toInt
    }
    
	//值调用顺序:隐式值 -> 隐式参数默认值 -> 前两者都没有 报错
    println(transform()) //结果:3 
    //方法调用时,使用小括号会导致隐式值无法转递 所以这里调用的是隐式参数的值
    
    println(transform)//结果:2
    //不使用小括号可以传递隐式值
  }
}
}

在Scala2.10后提供了隐式类,可以使用implicit声明类,隐式类的非常强大,同样可以扩展类的功能,在集合中隐式类会发挥重要的作用。 其所带的构造参数有且只能有一个 隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的。

object ScalaImplicit { 
        
    def main(args: Array[String]): Unit = { 
        
        val emp = new Emp()
        emp.insertUser()
    }
    class Emp { 
        
    }
    //将一个类Emp 变成另外一个类 User
    implicit class User( emp : Emp) { 
        
        def insertUser(): Unit = { 
        
            println("insert user...")
        }
    }
}

二、JVM

1、JVM是什么?

JVM(java虚拟机Java Virtual Machine), 是一种抽象化的计算机, 在运行时负责将Java程序的.class文件,有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。具有的特性。

JVM可以将Java语言通过各种翻译成各个平台(windows、linux等)能读懂的语言因此可以跨平台。

JVM ,用以把Java语言编译后的.class文件翻译成系统能读懂的, 如果别的语言也翻译成了.class二进制字节码文件,也可以在JVM里运行,如Scala。

2、类加载机制:

类加载器负责加载class文件,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构,并且ClassLoader只负责文件的加载,至于它是否可以运行,则由Execution Engine决定

从类被加载到虚拟机内存中开始,到卸御出内存为止,它的整个生命周期分为7个阶段:加载--验证--准备--解析--初始化--使用--卸载。其中验证、准备、解析三个部分统称为连接。

    • 将class文件加载在内存中。
    • 将静态数据结构(数据存在于class文件的结构)转化成方法区中运行时的数据结构。
    • 在堆中生成一个代表这个类的java.lang.Class对象,作为数据访问的入口
  • :确保加载的类符合JVM规范与安全。保证被校验类的方法在运行时不会做出危害虚拟机安全的事件

  • :为static变量在方法区中分配空间,设置变量的初始值。例如static int a=3,在此阶段会a被初始化为0;

  • :解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

  • :为类的静态变量赋予正确的初始值

  • :正常使用

  • :GC把无用的对象从内存中卸载

在这里插入图片描述

3、类的加载顺序:

1):负责加载JAVA_HOME中jre/lib/rt.jar里所有的 class,由 C++ 实现,不是 ClassLoader 子类。

2):负责加载Java平台中扩展功能的一些 jar 包,包括JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的 jar 包。

3):负责加载 classpath 中指定的 jar 包及目录中 class。

4):属于应用程序根据自身需要自定义的 ClassLoader,如 Tomcat、jboss 都会根据 J2EE 规范自行实现 ClassLoader。

  • ,从 Custom ClassLoaderBootStrap ClassLoader 逐层检查,只要某个 Classloader 已加载就视为已加载此类,保证此类只所有 ClassLoader 加载一次。

  • ,也就是由上层来逐层尝试加载此类。

4、双亲委派机制

  • JVM在加载类时默认采用的是双亲委派机制:

  • 就是某个特定的类加载器在接到加载类的请求时,首,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

5、JVM中内存区域的划分​

JVM运行时数据区域:由5块部分组成,分别是堆,方法区,虚拟机栈,本地方法栈,以及程序计数器组成。 可以根据内存是否线程共享划分成:

  • 1.java文件经过编译之后变成class字节码文件
  • 2.字节码文件通过类加载器被搬运到jvm虚拟机当中来
  • 3.虚拟机当中主要有五大块
    • : 加载好的类,常量,静态变量等。线程共享区域
    • : new的对象,对象实例和数组等。线程共享区域
    • : 局部变量 。线程私有区域
    • :调用一些底层的C程序实现。线程私有区域
    • : 存储下—条即将要执行的字节码指令地址,由执行引擎读取下一条指令,程私有区域

  • 一个进程中存在 多个线程 ,
  • 每个线程中,都存在自己的栈和程序程序计数器,
  • 一个进程中,共用一个堆和一个方法区 。
  • 局部变量在栈上,静态变量在方法区中、成员变量在堆上

5.1、堆

  • 堆内存:存放的是new的对象,对象实例和数组等,垃圾收集器就是收集这些对象,然后根据GC算法回收。

  • 一个JVM实例只存在一个堆内存,堆内存也是Java内存管理的核心区域,所有的线程共享Java堆内存

  • JVM启动的时候即被创建,堆内存的大小是可调节的。

  • 方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除

  • 堆内存是Gc执行垃圾回收的重点区域

在jdk1.8当中已经不存在永久代这一说了,取而代之的是元数据区,

5.2、方法区

  • 方法区存储了每一个类的结构信息,用来存储已经被虚拟机加载的类信息、常量、静态变量等;各个线程共享的内存区域,在JVM启动的时候被创建, 关闭JVM就会释放这个区域的内存。

  • 方法区的大小决定了系统可以保存多少个类,如果定义太多类,加载大量的第三方的Jar包,Tomcat部署过多工程,导致方法区溢出,虚拟机同样会抛出内存溢出OOM:PermGenspace或者Metaspace

5.3、虚拟机栈

  • 虚拟机栈,也叫Java栈,每个线程创建时都会创建一个虚拟机栈,内部保存一个个栈帧,对应着一次次的Java方法调用
  • 生命周期和线程的—致,线程被销毁,虚拟机栈也就随之销毁,不存在垃圾回收问题,
  • 虚拟机栈,主管Java程序的运行(主要是方法的执行),保存方法的局部变量(8种基本数据类型、对象的引用地址)、部分中间结果,并参与方法的调用和返回。
  • 栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,每个方法执行的同时都会创建一个栈帧,用于存储局部变量表等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。
  • 栈的大小和具体JVM的实现有关,通常在256K~756K之间,与等于1Mb左右
  • 栈管运行,堆管存储

5.4、本地方法栈

  • 虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,
  • 本地方法栈,为虚拟机使用到的Native方法服务(比如C语言写的程序和C++写的程序)
  • Java虚拟机栈管理Java方法的调用,而本地方法栈用于管理本地方法的调用

5.5、程序计数器

  • 程序计数器是内存区域中唯一 一块不存在OutOfMemoryError的区域
  • 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。

5.6、本地方法接口

作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序,目前该方法使用的越来越少了,除非是与硬件有关的应用

6、 栈内存溢出

栈是线程私有的,他的生命周期与线程相同,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。局部变量表又包含基本数据类型,对象引用类型;

  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常,方法递归调用产生这种结果。

  • 如果Java虚拟机栈可以动态扩展,并且扩展的动作已经尝试过,但是,或者在,那么Java虚拟机将抛出一个OutOfMemory 异常。(线程启动过多)

  • 参数 -Xss 去调整JVM栈的大小

7、堆内存什么要分成新生代,老年代,持久代

  • 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC。老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,所以需要分为Eden和Survivor。

  • Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。

  • 设置两个Survivor区最大的好处就是解决了,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)

8、JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代

  • 当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区。

  • 大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年态; 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。

  • 老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存堆 – 包括年轻代和年老代。

  • Major GC 发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。

9、垃圾回收

10 、STW

11. 垃圾收集器,各自的优缺点,重点 cms和G1

  • 1)Serial收集器: 单线程的收集器,收集垃圾时,必须stop the world,使用复制算法。
  • 2)ParNew收集器: Serial收集器的多线程版本,也需要stop the world,复制算法
  • 3)Parallel Scavenge收集器: 新生代收集器,复制算法的收集器,并发的多线程收集器,目标是达到一个可控的吞吐量。如果虚拟机总共运行100分钟,其中垃圾花掉1分钟,吞吐量就是99%。
  • 4)Serial Old收集器: 是Serial收集器的老年代版本,单线程收集器,使用标记整理算法。
  • 5)Parallel Old收集器: 是Parallel Scavenge收集器的老年代版本,使用多线程,标记-整理算法。
  • 6): 是一种以获得最短回收停顿时间为目标的收集器,标记清除算法,运作过程:初始标记,并发标记,重新标记,并发清除,收集结束会产生大量空间碎片。
  • 7): 标记整理算法实现,运作流程主要包括以下:初始标记,并发标记,最终标记,筛选标记。不会产生空间碎片,可以精确地控制停顿。

  • 1) CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用; G1收集器收集范围是老年代和新生代,不需要结合其他收集器使用;
  • 2)CMS收集器以最小的停顿时间为目标的收集器; G1收集器可预测垃圾回收的停顿时间
  • 3)CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片 G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。

12、调优

三、Java基础

1、数据类型

自动转换:char–> byte–>short–>int–>long–>float–>double

所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。

String s1 = "abc";            // 常量池
String s2 = new String("abc");     // 堆内存中
System.out.println(s1==s2);        // false两个对象的地址值不一样。
System.out.println(s1.equals(s2)); // true

  • 1)int:是基本数据类型,int 变量存储的是数值。Integer 是引用类型,实际是一个对象,Integer 存储的是引用对象的地址。
  • 2)Integer:是一个对象,需要存储对象的元数据,占用更多的内存。但是 int 是一个原始类型的数据,所以占用的空间更少。
  • 3) new Integer() :生成的变量指向堆中新建的对象,非 new 生成的 Integer 变量指向的是 java 常量池中的对象,两者在内存中的地址不同。

  • 1)String:字符串常量,字符串长度不可变。Java中String 是immutable(不可变)的。用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。
  • 2)StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。Java.lang.StringBuffer 线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
  • 3)StringBuilder:字符串变量(非线程安全)。在内部 StringBuilder 对象被当作是一个包含字符序列的变长数组。 -4)基本原则:如果要操作StringStringBuilder,用StringBuffer

  • ArrayList 是 List 接口的一种实现,它是使用的。

  • LinkedList 是 List 接口的一种实现,它是使用的。

  • ArrayList 遍历和查找元素比较快。LinkedList 遍历和查找元素比较慢。

  • LinkedList 添加、删除元素比较快。ArrayList 添加、删除元素比较慢。

    基本数据类型的特点:直接存储在栈(stack)中的数据 引用数据类型的特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存

引用数据类型,,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体

深拷贝和浅拷贝,针对

  • 浅拷贝,只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
  • 深拷贝,会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

2、变量类型

public class Variable{ 
        
 	static int allClicks=0; // 类变量
 	String str="hello world"; // 实例变量 
public void method(){ 
         
int i =0; // 局部变量
 	}
 }
  • 1)类变量 (静态变量):声明在类中方法体之外,用 static 修饰,属于整个类。可通过对象名或类名来调用。

  • 2)实例变量(成员变量):声明在类中方法体之外,没有 static 修饰,在创建对象的时候实例化。可以被类中方法、构造方法和特定类的语句块访问。

  • 3)局部变量:在方法、构造方法或语句块中定义的变量 。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。

  • 类变量在方法区中、实例变量在堆上 ,局部变量在栈上

3、面向对象编程

OOP: object -oriented-proramming 面向对象编程

面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

  • 1)(class):数据类型,是一个模板,它描述一类对象的行为和状态。 它是对某一类事物整体描述定义,但是并不能代表某一个具体的事物.
  • 2):对象是类的一个具体实例,有状态和行为。
  • 3)(instance):数据
  • 3)(field):变量名.字段名,访问field

  • 1):表示一个class包含多个field,用private修饰field,可以拒绝外部访问。
  • 2):表示一个class使用extends继承父类,可获得父类所有功能,只需编写新功能
  • 3):表示方法的调用,总是作用于对象的实际类型,对象能执行的方法,主要看左边,和右边的关系不大

1.父类引用指向子类的对象 2.把子类转换为父类,向上转型; 3.把父类转换为于类,向下转型;强制转换,((sudent)s2).eat()

  • 1):方法名为类名,参数无限制,无返回值,用于初始化实例,可定义多个构造方法,未定义时编译器创建默认构造方法,
  • 2):同一类中,多个方法的方法名与返回值类型相同,但参数(个数、类型、位置)不同,目的在于相同功能的方法使用一个名字,便于调用。
  • 3)@override,子类重写父类的方法,方法签名(方法名称、参数和返回类型) 要一样,重写必须要有继承
  • 方法,在方法,都可以用来实现不同的功能。

  • 1): 定义了方法,但没有具体的执行代码,那么这个方法为抽象方法, 用abstract修饰,定义了子类必须实现的接口规范,实现代码的重用
  • 2)的类,也可以有非抽象方法。定义接口规范,不允许被实例化,只能使用一次继承关系
  • 3)没有实例字段,一个类却可以实现多个接口,但只能继承一个抽象类
  • 4):是一种符合命名规范的class,方便IDE工具读写属性,传递数据,枚举属性
  • 5):定义在一个class内部的class,可,破坏原有类的程序结构(属性、构造方法、普通方法、内部类)。

4、修饰符

,有 2 种访问权限:,有 4 种访问权限:

  • 1) public : 表示任何地方的其他类都能访问。
  • 2) private : 表示只有自己类能访问。
  • 3) default :同一个包的类可以访问。
  • 4) protected :表示同一个包的类可以访问,其他的包的该类的子类也可以访问。

  • 1) abstract: 表示是抽象类。 使用对象:类、接口、方法
  • 2) static: 可以当做普通类使用,而不用先实例化一个外部类。(用他修饰后,就成了静 态内部类了)。 使用对象:类、变量、方法、初始化函数(注意:修饰类时只 能修饰 内部类 )
  • 3)final: 表示类不可以被继承。 使用对象:类、变量、方法

  • this :指向对象本身的指针,形参与成员名字重名,用 this 来区分。
  • super :父类对象的一个指针。

5、运算符

1)算术运算符、2)关系运算符、3)位运算符、4)逻辑运算符、5)赋值运算符、6)其他运算符

循环结构 : for, while 及 do…while

Math.floor :向下取整。Math.ceil :向上取整。Math.round :四舍五入取整

装箱和拆箱的概念有点特别。

6、反射与注解

Java反射机制提供的功能

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

标签: s2压力变送器器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台