java基础总结二--让大学生活不再迷茫

承接我的上一篇博客java基础总结1
https://blog.csdn.net/weixin_43410352/article/details/87073372
10.java的三大特性
封装:这是java受欢迎的重要原因,它将所有功能方法都封装进一个对象当中,通过对象 .点就可以很方便的使用,完全不用知道里面是如何使用的,比如产生一个随机数 你只需要

Random random=new Random(); 
String number=random.nextInt(99);

至于这个数字如何产生的你不用去追究它,只需创建对象调用方法即可,现在的封装已经做的很好了,有经验的同学可以直接通过javaAPI进行学习,效率更高。

继承:
1.java只允许单继承意思只能有一个父亲
2.继承下来能拥有父类非private所有的方法和属性
3.子类可以拥有自己独有的方法
4.子类可以重写父类的方法,但是访问权限不能比父类还要严格
比如父类为procted权限
子类重写的属性或方法只能是procted或者public 同理 父类为public子类也只能使用public

继承提高了代码的复用性和灵活性

多态:
同一个对象,在不同时刻体现出来的不同效果

多态使用的前提 :
1.继承或者接口实现
2.要有方法的重写(不能调用子类独有的方法)
3.要有父类或者父接口引用指向子类 如 Fu f=new Zi();
父类为形参,子类为实参
3、多态的分类:

1)具体类多态

class Fu{}
class Zi extends Fu{}

Fu f= new Zi()//父类引用指向子类

2)抽象类多态

abstract class Fu{}
class Zi extends Fu{}

Fu f= new Zi();//抽象父类引用指向子类

3)接口多态
  
interface Fu{}
class Zi implements Fu{}
Fu f= new Zi();//父接口引用指向子类

使用场景:
1.使用父类作为方法的形参

public class Test3 {
    public static void main(String[] args) {	
		Baby baby=new Baby();
		baby.say();//调用子类独有的方法必须创建子类对象
	
		God god=new God();
		Parent parent=new Parent();
		god.teach(baby);
		god.teach(parent);	
	}
}

class God
{
	public void teach(Person p)
	{
		p.walk();
	}
	
}

interface Person
{  //规定接口部分
	public void walk();
}

class Parent implements Person
{
	public void walk()
	{
		System.out.println("大人都会走路");
	}
}

class Baby implements Person
{
	public void walk()
	{
		System.out.println("Baby还不会行走");
	}
	
	public void say()
	{
		System.out.println("Baby会说婴语");
	}
	
}

2.使用父类作为方法的返回值。

 public static void main(String[] args) {	
      God god=new God();
      god.get("baby");
    	
	}
class God
{
	public Person get(String type)
	{
		Person person=null;
		if(type.equals("parent"))
		{
			person=new Parent();         
			System.out.println("类型为:"+person.getClass().getName());
		}
		if(type.equals("baby"))
		{
			person=new Baby();
			System.out.println("类型为:"+person.getClass().getSimpleName());
		}else
		{
			System.out.println("类型为:"+null);
		}
		return person;
	}
	
}
结果为:类型为:Baby

3.继承下父类作为形参引用子类对象

例如下面的例子 学生和老师都是属于人它们有共通的方法和自己独有的方法学生类重写了父类的方法而老师类没有重写父类的方法

public class Test3 {
	public static void main(String[] args) {
		Preson student=new Student();
		
		Preson teacher=new Teacher();
		
		student.eat("学生类的eat");//子类重写了父类的eat方法父类eat方法被覆盖了  调用的是子类的eat
		teacher.eat("老师"); //因为子类没有重写父类的eat方法所有调用的是父类继承下来的eat方法
		Teacher teacher2=new Teacher();
		teacher2.teach();//如果要调用子类独有的的方法要创建子类对象
		
	}
}

class Preson
{
	public void eat(String a) {
		System.out.println("父类eat方法"+"----"+a);
	}
}
class Student extends Preson
{
	public void eat(String a) {
		System.out.println("执行了"+a);
	}
	
}
class Teacher extends Preson
{
	public void teach() {
		System.out.println("老师教书");
	}
}
结果:
执行了学生类的eat
父类eat方法----老师
老师教书

易混点:

覆盖:又叫重写,Override。多态是java的特性,覆盖是表现多态特性的具体做法。《Effective Java》有一个章节特别提出了,如
果是覆盖方法,请一定记得加上@Override,在接下来的代码描述中你会看到,很多种方法混杂在一起的时候看起来是多么的难受

重载:重载只发生在一个类中,记住这点很重要,这也是跟覆盖这个概念撇清关系的最重要一点。重载要求同一个类中方法名相同
而参数列表不同。参数列表,就是入参的个数,类型,顺序。抓住定义中的这两点,其他的通过什么返回值,访问权限,异常来重
载一个方法那就是扯淡,混淆,不行。

11.异常

程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?Java提供了更加优秀的解决办法:异常处理机制。

异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
Java中的异常可以是函数中的语句执行时引发的,也可以是程序员通过throw 语句手动抛出的,只要在Java程序中产生了异常,就会用一个对应类型的异常对象来封装异常,JRE就会试图寻找异常处理程序来处理异常。
Throwable类是Java异常类型的顶层父类,一个对象只有是 Throwable 类的(直接或者间接)实例,他才是一个异常对象,才能被异常处理机制识别。JDK中内建了一些常用的异常类,我们也可以自定义异常。。

Java异常机制用到的几个关键字:try、catch、finally、throw、throws。
• try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
• catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
• finally – finally语句块总是会被执行(不管你在try-catch中是否return)。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。良好的编程习惯是:在try块中打开资源,在finally块中清理释放这些资源。
• throw – 用于抛出异常。
• throws – 用在方法签名中,用于声明该方法可能抛出的异常。

在这里插入图片描述

错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。

异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。

这里主要讲解什么是运行时异常和检查时异常

RuntimeException运行时异常:
如上图RuntimeException类及其子类都叫运行时异常
特点:java编译器不会检查它,如数组越界时产生的IndexOutOfBoundsException异,和除数为0产生的ArithmeticException的异常。如果你不通过try-catch捕获,程序就终止了

检查时异常:
Exception类本身,以及Exception的子类中除了"运行时异常"之外的其它子类都属于被检查异常。常见的有io流的读写都要抛出IOException异常
特点:java编译器会检查他,除非你手动抛出或者try捕获否则编译器不会让你通过

实际开发中常常自定义异常来满足实际需求
你可以设计运行时异常也可以设计检查时异常 分别通过继承不同的类即可
如设计检查时异常继承Exception,同理运行时异常继承RuntimeException

需要注意的是
1.
try-catch-final在这三者间定义局部变量,3者互不相同,都不能使用对方定义的量,这也是为什么经常在要扩大作用域
例子:
String name=null; //定义在try-catch外面是为了扩大作用域
try
{
int a=5;
Sysotem.out.println(“能使用name”)
}catch(…)
{
Sysotem.out.println(“能使用name”)
Sysotem.out.println(a)//报错,无法使用
}final
{
Sysotem.out.println(“能使用name”)
Sysotem.out.println(a)//报错,无法使用
}

每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的,只有第一个匹配的catch会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义

java异常处理机制和某些语言不一样它是将发生异常的地方,交到能处理异常的地方,然后往下执行。

也就是说:当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。
有的编程语言当异常被处理后,控制流会恢复到异常抛出点接着执行,这种策略叫做:resumption model of exception handling(恢复式异常处理模式 )
而Java则是让执行流恢复到处理了异常的catch块后接着执行,这种策略叫做:termination model of exception handling(终结式异常处理模式)

例子:

public static void main(String[] args){
        try {
            foo();
        }catch(ArithmeticException ae) {
            System.out.println("处理异常");
        }
        System.out.println("处理后干了。。。。");//会执行
}
public static void foo(){
        int a = 5/0;  //异常抛出点
        System.out.println("直接跳转到最近的匹配的异常处理catch块");  /不会执行
}

12.多线程
1、进程和线程:
一个程序就是一个进程,一个进程至少包含一个线程
2、jvm多线程的启动是多线程吗?
java的虚拟机jvm启动的是单线程,就有发生内存泄露的可能,而我们使用java程序没出现这样的问题,
也就是jvm启动至少有两个线程,一个执行java程序,一个执行垃圾回收。所以是多线程。
2、多线程的优势:
解决了多部分同时运行的问题,提高效率
3、线程的弊端:
线程太多会导致效率的降低,因为线程的执行依靠的是CPU的来回切换。
4、什么叫多线程:
一个进程中有多个线程,称为多线程。

5、实现多线程的方法:
实现多线程可以通过继承Thread类和实现Runnable接口。
然后重写run方法即可
run()方法中的内容称为线程体,它就是这个线程需要执行的工作。

简单介绍一下线程生命周期

new Thread进入 (新建状态) ->调用start方法进入 (就绪状态)->当线程分配到cpu (进入到运行状态) ->阻塞状态->run()方法执行完,或者被强制性地终止进入死亡状态

进入阻塞状态的情况:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁 巧记:抱着锁睡觉)

sleep不释放锁例子:

public class Test4 implements Runnable
 {
     private String lock = "lock";
     private int count = 0;
     public static void main(String[] args)
     {
         Test4 test = new Test4();
       new Thread(test).start(); 
       new Thread(test).start();  
    }
    
     @Override
     public void run()
     {
         while(count<10){
             System.out.println(Thread.currentThread().getName()+" 开始抢锁!");
             synchronized (lock)
            {
                 System.out.println(Thread.currentThread().getName()+" 抢到锁了!"+(count++));
                 try
                 {
                    Thread.sleep(5000);
                } catch (InterruptedException e)
                 {
                     e.printStackTrace();
                 }
                 System.out.println(Thread.currentThread().getName()+" 准备下一波!"+(count++));
             }
             
}
     }
 }
运行结果:
Thread-1 开始抢锁!
Thread-1 抢到锁了!0
Thread-0 开始抢锁!

运行到此处Thread-1会休眠5秒,进入阻塞状态,时间到了才会释放锁

sleep(),yied(),wait(),join()区别对比
1.sleep Thread类的静态方法 不会释放锁 让线程进入阻塞状态,需要进行异常捕获或者显示抛出异常

2.yied让步 Thread类的静态方法 与sleep方法相似,它也可以让当前正在执行的线程暂停,不过它不是进入阻塞状态,而是进入就绪状态,当然也有可能进入就绪状态,cpu又调度到它,yield方法则没有声明抛出任务异常。
sleep方法比yield方法有更好的可移植性,通常不要依靠yield方法来控制并发线程的执行

3.join(线程的合并)含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,Thread类提供了join方法来完成这个功能,注意,它不是静态方法,属于Thread方法。
意思是说调用了该方法的线程,必须先让它执行完毕,其他线程都等到起

4.wait方法让当前进入synchronized代码块的线程进入等待状态,同时释放锁,让其他线程进入,只有当前锁对象调用了notify方法才会重新进入运行状态
wait()和notify()因为会对对象的“锁标志”进行操作,所以他们必需在Synchronized函数或者 synchronized block 中进行调用。如果不在synchronized 函数或 non-synchronized block 中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。。

wait和notify都属于Object的方法

经典例子:


public class Test4 
 {
    
     public static void main(String[] args)
     {    
         new Thread(new T1(),"线程1").start(); 
         new Thread(new T2(),"线程2").start();   
    }
     
   static  class T1 implements Runnable {
    		
    	    public void run()
    	    {
    	    	synchronized(Test4.class)
    	    	{
    	    	System.out.println(Thread.currentThread().getName()+"进入了");
    	    	try {
    	    	
					Test4.class.wait();
					
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
    	    	System.out.println(Thread.currentThread().getName()+"继续执行");
    	       
    	    }
    	    }

    		}

   static	class T2 implements Runnable{
    		
    	    @Override
    	    public void run()
    	    {
    	    	synchronized(Test4.class)
    	    	{
    	    		System.out.println(Thread.currentThread().getName()+"进入了");
    	    		
    	    		Test4.class.notify();//唤醒刚刚进入wait的线程
    	    		
    	    		try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
    	    		System.out.println(Thread.currentThread().getName()+"继续执行");
    	    		
    	    	}
    	            

    	    }

    	}

 }

运行结果:在这里插入图片描述如果将 Test4.class.notify();//唤醒刚刚进入wait的线程注释掉
在这里插入图片描述那么线程1将一直处于挂起状态

线程死锁问题:
比如现实当中例子:期末了小红都各自有一本书,大家在复习中需要别人手中的书,但是都不想把书先给别人,小红说你先把书借我复习,我才给你,小明也说你先给我我才给你,这样都不想让,造成了死锁

class Book
{
public String name;
public float price;

public Book(String name, float price)
{
    this.name = name;
    this.price = price;
}

}

class Student implements Runnable
{
private String studentName;
private Book book1;
private Book book2;

public Student(String studentName,Book book1, Book book2)
{
    this.book1 = book1;
    this.book2 = book2;

    this.studentName = studentName;
}

public void run()
{
    synchronized(this.book1)
    {
        System.out.println(this.studentName+"拿到了"+this.book1.name +"开始写论文");
         try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        System.out.println(this.studentName+"完成一半需要"+this.book2.name);
        
        synchronized(this.book2)
        {
            System.out.println(this.studentName+"拿到了"+this.book2.name +"继续写论文");
        }
        System.out.println(this.studentName+"完成了论文");
    }
    
}

}

class Test
{
public static void main(String[] args)
{
Book book1 = new Book(“汇编原理”,23.5f);
Book book2 = new Book(“算法导论”,85.5f);

    Thread xh = new Thread(new Student("小红",book1,book2));
    Thread xm = new Thread(new Student("小明",book2,book1));
    xh.start();
    xm.start();
}

}

下一篇博客:java基础总结三
https://blog.csdn.net/weixin_43410352/article/details/87347385

借鉴了许多资料,就不一一列举了
有什么不好的地方,希望大家能提出来。

继续坚持 加油!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值