java基础知识

基本知识:

main函数可以保证该程序的独立运行,它是程序的入口,它会被JVM所调用。

if else 结构 简写格式:变量 = (条件表达式)?表达式1:表达式2;

三元运算符:好处:可以简化if else代码。

                            弊端:因为是一个运算符,所以运算完必须要有一个结果。

转义字符:通过\ 来转变后面字母或者符号的含义。

                     \n:换行。

                     \b:退格。相当于backspace。

                     \r:按下回车键。window系统,回车符是由两个字符来表示\r\n.

                     \t:制表符。相当于tab键。

 

逻辑运算符用于连接boolean类型的表达式

& : 只要两边的boolean表达式结果,有一个为false。那么结果就是false。只有两边都为true,结果为true。

| : 两边只要有一个为true,结果为true。只有两边都有false,结果为false

^ : 两边相同结果是false,两边不同结果是true

&和&&的区别:

&:无论左边是true是false。右边都运算。

                   &&:当左边为false时,右边不运算。

|和||的区别:

                   |:两边都参与运算。

                   ||:当左边为true。右边不运算。

 

if和switch语句很像。具体什么场景下,应用哪个语句呢?如果判断的具体数值不多,而是符合byte short int char这四种类型。虽然两个语句都可以使用,建议使用swtich语句。因为效率稍高。其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广

 

一个数异或同一个数两次,结果还是那个数

 

For嵌套规律:

尖朝上,可以改变条件。让条件随着外循环变化。

尖朝下,可以改变初始化值,让初始化随着外循环变

 

无限循环的最简单表现形式:for(;;){},while(true){}

break和continue单独存在时,下面可以有任何语句。因为都执行不到

 

静态:static。

用法:是一个修饰符,用于修饰成员(成员变量,成员函数).

当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,

还可以直接被类名调用。类名.静态成员。

 

 

static特点:

1,随着类的加载而加载。

   也就说:静态会随着类的消失而消失。说明它的生命周期最长。

2,优先于的对象存在

明确一点:静态是先存在。对象是后存在的。

3,被所有对象所共享

4,可以直接被类名所调用。

 

实例变量和类变量的区别:

1,存放位置。

         类变量随着类的加载而存在于方法区中。

         实例变量随着对象的建立而存在于堆内存中。

2,生命周期:

         类变量生命周期最长,随着类的消失而消失。

         实例变量生命周期随着对象的消失而消失。

 

静态使用注意事项:

1,静态方法只能访问静态成员。

         非静态方法既可以访问静态也可以访问非静态。

2,静态方法中不可以定义this,super关键字。

         因为静态优先于对象存在。所以静态方法中不可以出现this。

3,主函数是静态的。

        

静态有利有弊

利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。

         可以直接被类名调用。

弊端:生命周期过长。

           访问出现局限性。(静态虽好,只能访问静态。

 

静态代码块:

格式:

static

{

         静态代码块中的执行语句。

}

 

特点:随着类的加载而执行,只执行一次,并优先于主函数。

用于给类进行初始化的。

 

构造代码块。

         作用:给对象进行初始化。

         对象一建立就运行,而且优先于构造函数执行。

         和构造函数的区别:构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化。构造代码快中定义的是不同对象共性的初始化内容

 

单例设计模式:解决一个类在内存只存在一个对象。

饿汉式:Single类一进内存,就已经创建好了对象。(建议使用)

         private  Single(){} //将构造函数私有化。

 

         privatestatic Single s = new Single(); //在类中创建一个本类对象

 

         publicstatic  Single getInstance()  //提供一个方法可以获取到该对象

         {

                   returns;

         }

懒汉式:对象是方法被调用时,才初始化,也叫做对象的延时加载

private static Single s = null;

         privateSingle(){}

         publicstatic Single getInstance()

         {

                   if(s==null)

                   {

                            synchronized(Single.class)

                            {                                   

                                     if(s==null)

                                               s= new Single();

                            }

                   }

                   returns;

         }

 

abstract 关键字,和哪些关键字不能共存。

final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。

private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。而抽象方法出现的就是需要被复写。

static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。可是抽象方法运行没意义。

 

内部类的访问规则:

1,内部类可以直接访问外部类中的成员,包括私有。

         之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式外部类名.this

2,外部类要访问内部类,必须建立内部类对象。

 

内部类定义在局部时,

1,不可以被成员修饰符修饰

2,可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。

 

异常:

是什么?是对问题的描述。将问题进行对象的封装。

------------

异常体系:

         Throwable

                   |--Error

                   |--Exception

                            |--RuntimeException

 

异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性。

                                     也就是说可以被throw和throws关键字所操作。

                                     只有异常体系具备这个特点。

 

 

--------------

throw和throws的用法:

 

throw定义在函数内,用于抛出异常对象。

throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。

 

 

当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,都在编译失败。

注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。

--------------

 

 

如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try。

 

异常有两种:

         编译时被检测异常

                   该异常在编译时,如果没有处理(没有抛也没有try),编译失败。

                   该异常被标识,代表这可以被处理。

         运行时异常(编译时不检测)

                   在编译时,不需要处理,编译器不检查。

                   该异常的发生,建议不处理,让程序停止。需要对代码进行修正。

 

 

 

--------------

异常处理语句:

try

{

         需要被检测的代码;

}

catch ()

{

         处理异常的代码;

}

finally

{

         一定会执行的代码;

}

 

有三个结合格式:

1.      try

         {                  

         }

         catch()

         {

         }

 

2.      try

         {        

         }

         finally

         {     

         }

3.      try

         {        

         }

         catch()

         {

         }

         finally

         {

         }

 

注意:

1,finally中定义的通常是 关闭资源代码。因为资源必须释放。

2,finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。

 

--------------

 

自定义异常:

         定义类继承Exception或者RuntimeException

         1,为了让该自定义类具备可抛性。

         2,让该类具备操作异常的共性方法。

 

         当要定义自定义异常的信息时,可以使用父类已经定义好的功能。

         异常异常信息传递给父类的构造函数。

         classMyException extends Exception

         {

                   MyException(Stringmessage)

                   {

                            super(message);

                   }

         }

 

自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。

--------------

异常的好处:

         1,将问题进行封装。

         2,将正常流程代码和问题处理代码相分离,方便于阅读。

异常的处理原则:

         1,处理方式有两种:try 或者 throws。

         2,调用到抛出异常的功能时,抛出几个,就处理几个。

                   一个try对应多个catch。

         3,多个catch,父类的catch放到最下面。

         4,catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。

                   也不要不写。

                   当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。

                   try

                   {

                            thrownew AException();

                   }

                   catch(AException e)

                   {

                            throwe;

                   }

 

 如果该异常处理不了,但并不属于该功能出现的异常。 可以将异常转换后,在抛出和该功能相关的异常。  

或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。

                   try

                   {

                            thrownew AException();

                   }

                   catch(AException e)

                   {

                            //对AException处理。

                            thrownew BException();

                   }

 

异常在子父类覆盖中的体现;

1,子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。

2,如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。

3,如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。

         如果子类方法发生了异常。就必须要进行try处理。绝对不能抛。

 

多线程:

进程:正在执行的程序。

线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)

进程中至少有一个线程。

对于JVM,启动时,只好有两个线程:jvm的主线程。jvm的垃圾回收线程。

 

如何在程序中自定义线程呢?

Java给我们提供了对象线程这类事物的描述。该类是Thread

该类中定义了,

创建线程对象的方法(构造函数).

提供了要被线程执行的代码存储的位置(run())

还定义了开启线程运行的方法(start()).

 

创建线程的第一种方式是:继承Thread类。原因:要覆盖run方法,定义线程要运行的代码。

 

步骤:

1,继承Thread类。

2,覆盖run方法。将线程要运行的代码定义其中。

3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。

 

如果自定义的类中有多线程要运行的代码。但是该类有自己的父类。

那么就不可以在继承Thread。怎么办呢?

Java给我们提供了一个规则。Runnable接口。

如果自定义类不继承Thread,也可以实现Runnable接口。并将多线程要运行的代码存放在Runnable的run方法中。

这样多线程也可以帮助该类运行。

这样的操作有一个好处:避免了单继承的局限性。

 

创建线程的第二种方式:实现Runnable接口。

步骤:

1,定义了实现Runnable接口。

2,覆盖接口的run方法。将多线程要运行的代码存入其中。

3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。

         为什么要传递?因为线程要运行的代码都在Runnable子类的run方法中存储。所以要将该run方法所属的对象。传递给Thread。让Thread线程去使用该对象调用其run方法。

4,调用Thread对象的start方法。开启线程。

 

两种方式的特点:

实现方式,因为避免了单继承的局限性,所以创建线程建议使用第二种方式。

 

线程的状态。

1,被创建。

2,运行。

3,冻结。

4,消亡。

 

其实还有一种特殊的状态:临时状态。

 

该临时状态的特点:

具备了执行资格,但不具备执行权。

 

冻结状态的特点:

放弃了执行资格。

 

多线程具备随机性。因为是由cpu不断的快速切换造成的。

就有可能会产生多线程的安全问题。


问题的产生的原因:

几个关键点:

1,多线程代码中有操作共享数据。

2,多条语句操作该共享数据。

 

当具备两个关键点时,

有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。

就会发生数据错误。

 

解决方法:

当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。

 

Java就对这种解决方式提供了专业的代码。

同步

同步的原理:就是将部分操作功能数据的代码进行加锁。

 

示例:火车上的卫生间。

 

同步的表现形式:

1,同步代码块。

2,同步函数。

两者有什么不同:

同步代码块使用的锁是任意对象。

同步函数使用的锁是this。

 

注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象。

         涉及到了单例设计模式的懒汉式。

 

同步的好处:解决了线程的安全问题。

 

弊端:

         较为消耗资源。

         同步嵌套后,容易死锁。

 

要记住:同步使用的前提:

         1,必须是两个或者两个以上的线程。

         2,必须是多个线程使用同一个锁。

         这是才可以称为这些线程被同步了。

 

死锁代码一定会写。但开发时一定注意避免。

 

Collection

 |--List:元素是有序的,元素可以重复。因为该集合体系有索引。

              |--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

              |--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

              |--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。

 

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。、

             |--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。HashSet是如何保证元素唯一性的呢?是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true。如果元素的hashcode值不同,不会调用equals。

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

|--TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0.

TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。  也种方式也成为元素的自然顺序,或者叫做默认顺序。

TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式,通过传入实现比较器comparator接口的子类,并复写其compare方法

 

装饰设计模式:

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。

装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值