关于java基础知识的一点总结

期末考试了,是时候写一篇关于java的复习博客了 【小总结】,我觉得值得初学者进阶一下的地方三、四、六、八、十

  • 文章目录
    • 一、基本语法的易错点
      • 1.java中基本数据类型所占字节数
      • 2.类型转换
      • 3.一个关于switch的小问题
    • 二、java常用的权限关键字需要注意的地方
    • 三、关于继承你不知道的
      • 1.继承之后的堆内存中的super区和this区
      • 2.extends与Implements
      • 3.继承与static
    • 四、对于多态的一些体会
      • 1.多态在java中的两种体现
      • 2.向上转型和向下转型
    • 五、异常
      • 1.异常的分类以及继承关系
      • 2.try***catch语句,finally,throw,throws
        • 1.try catch的执行顺序
        • 2.如果一个try语句之中同时有多个catch
        • 3.finally
        • 4.恶心人的地方,try…catch…finally中的return
        • 5.Throwable接口中的常见方法
        • 6.throws的方式处理异常
        • 7.throw和throws的区别:
        • 8.自定义异常:
    • 六、Java中的传参方式
    • 七、JavaIO
      • 1.输入流和输出流与输入和输出
      • 2.流的特点
      • 3.流的分类
        • (1).按处理数据单位来分
        • (2).按角色来分
      • 4.常用的流作用概述
      • 5.InputStream类的主要方法
      • 6.关于FileInputStream类中的read()方法的一个小问题
      • 7.当然,辛国栋老师讲的IO操作还有很多,小生收益很大,就不再一一列出了。
      • 8.文件流在安卓开发上的应用
    • 八、泛型
    • 九、类图如何画(类之间的关系对应的线要记住)
      • 1.继承关系
      • 2.实现关系
      • 3.依赖关系
      • 4.关联关系
      • 5.聚合关系
      • 6.组合关系
      • 7.单个class,interface,如何画
    • 十、关于接口中的权限声明的问题
      • 1.default:
      • 2.接口中的变量和方法都能用哪些权限词修饰(建议你一定要看看)

文章目录

一、基本语法的易错点

1.java中基本数据类型所占字节数

数据类型 所占字节
byte 1
short 2
int 4
long(定义long型数据时加后缀“L”) 8
float 4
double 8
char (一般为2)不一定,详见https://blog.csdn.net/qq_21125183/article/details/85236267
boolean(java规范中并没有定义boolean类型的大小) (查阅其他博客)单个的boolean再JVM中占4个字节,在数组中每个boolean在JVM中占1个字节

2.类型转换

1.自动类型转换的等级(由低到高):byte,short ,char—> int —> long —> float —> double
2.byte,short,char在一起运算时,首先转换为Int类型。
如这样的代码就会提示类型不匹配的错误:

   public class Client {
	
	public static void main(String args[]) {
		byte b1 = 5;
		short s1 = 6;
		short s2 = b1+s1;//会有类型不匹配的错误,提示你进行cast
	}
}

3.一个关于switch的小问题

不说了,直接上图,自行体会
关于java基础知识的一点总结_第1张图片
关于java基础知识的一点总结_第2张图片

关于java基础知识的一点总结_第3张图片

二、java常用的权限关键字需要注意的地方

1.首先你要知道java中的权限关键字有:private,default(其实就是默认的),protected,public
2.其次java和c++的权限关键字是不一样的,java有default而c++没有
3.上表格

关键字 本类及其内部方法 同一个包的类 继承类 其他类
private 不可 不可 不可
default 对于子类:若和它在一个包里则可调用,不和它在一个包里不能调用 不可
protected 只要是子类,不管在不在一个包里都可以调用 不可
public

4.另外一定要注意,这里的default是不能声明出来的,比如如果一个类中有
default int x;则会报错,这个default意思就是不添加任何权限修饰词,int x。
另外default关键字只用在2个地方
(1)switch
(2)Interface的方法修饰词,(可以让虚拟方法有方法体),具体想了解详细的话,查阅这个博客
link.

三、关于继承你不知道的

1.继承之后的堆内存中的super区和this区

注意一点,子类继承父类之后的堆内存中分为super区和this区
看这样一个例子:

   public class Client {
	
	public static void main(String args[]) {
		//Father father = new Father();
		Son son = new Son();
		System.out.println(""+son.getA());	
	}
}

public class Father {
	private int a = 1;
	public int getA() {
		return a;
	}

	public void setA(int a) {
		this.a = a;
	}
}


public class Son extends Father{
	
	private int a = 3;
	
}

最后的输出结果是1
这个知识点详见:link.
例如这样一个语句Son son = new Son();
这句话在执行的时候可以把son理解成一个指针,存在栈中,它应该指向一个Son的对象(注意这个“应该”两个字,为后文中的向上转型做了铺垫哦),此处它指向堆里的一片内存区域,这个内存区是一个Son的对象,(因为new之后是一个Son的对象),它在访问Son类中的方法或属性的时候,先在this区进行寻找,如果找到了则执行,找不到再去super区寻找。

2.extends与Implements

子接口extends父接口,不能用Implements,并且一个子接口可以extends多个父接口。
虚拟类implements接口,不能用extends

3.继承与static

继承与static:
1.父类中的static方法:可以继承,可以重写,但是子类不能用非静态方法重写静态方法,会报错
2.父类中的static变量:可以继承,可以重写,若是子类中有一个与父类同名的非静态变量,比如父类有static int a ,子类有int a,则子类不再有static int a,但是super区仍然有static int a 。
此时直接用类名调用Son. 的时候会提示有a,但会显示属于Father
3.向上转型的时候:会调用父类的static方法及变量

四、对于多态的一些体会

1.多态在java中的两种体现

(1):方法的重载以及覆写
(2):对象的多态性

2.向上转型和向下转型

1…向上转型:
父类的声明却接收一个子类对象(也可以说成,用父类声明,用子类实例化),如代码所示

public class Father {

	public void print() {
		System.out.println("father");
	}
}

public class Son extends Father{
	@Override
	public void print() {
		
		System.out.println("son");
		
	}

	public void printSon() {
		System.out.println("printSon");
	}
}

public class Client {
	
	public static void main(String args[]) {
		Father father = new Son();
		father.print();		
	}
}

输出结果为:
son
值得注意的是这时候这个father是不能调用Son类型中的printSon()方法的,把这个father看成一个指针,它的类型是Father,所以在索引的时候,他能寻找的属性和方法(可以理解为按名字寻找)只有Father类中的属性和方法,但是在它指向的堆内存是一个Son的对象,前面说过了,在堆中寻找的时候先在this区进行寻找。
但其实它的本质是一个Son的对象,
当我加上这一行代码时

System.out.println(father.getClass().getSimpleName());

下面多输出了这样一条语句
Son
所以证明了它的本质还是一个Son的对象。
2.向下转型
值得注意的是直接向下转型是会报错的(其实这样根本不是向下转型的定义),如

Son son = new Father();//会报错

可见这样是会报错的
来看真正的向下转型

Father father = new Son();
		father.print();
		Son son = (Son) father;
		son.print();
		son.printSon();

输出结果
son
son
printSon
这个我就不再具体解释了,要学会举一反三嗷。

五、异常

首先声明一下,这里大多数是我们老师的课件,我拿来整理总结了一下,(我这菜鸡水平哪有这么厉害)

1.异常的分类以及继承关系

关于java基础知识的一点总结_第4张图片

2.try***catch语句,finally,throw,throws

这里为了应付考试,有以下几种恶心人的地方(是真的恶心)

1.try catch的执行顺序

出现异常时,加入try catch语句后,try{}捕获语句中出现异常后,try中这句话后面的语句不再执行,直接跳转到对应的catch,在该catch执行后,继续执行try…catch后的语句,上代码:

package edu.hit;

public class Demo3_Exception {
	public static void main(String[] args) {
		Demo2 d = new Demo2();
		try {
			int x = d.div(10, 0);
			System.out.println(x);
		} catch (ArithmeticException a) { // ArithmeticException a = new ArithmeticException();
			System.out.println("出错,除数为零");
		}
		System.out.println("1111111");
	}
}

class Demo2 {
	public int div(int a, int b) {
		return a / b;
	}
}

运行结果为
出错,除数为零
1111111

下面这个也能证明这一点:

package edu.hit;

public class Demo4_Exception {
	public static void main(String[] args) {
		int a = 10;
		int b = 0;
		int[] arr = { 11, 22, 33, 44, 55 };
		try {
			System.out.println(a / b);
			System.out.println(arr[10]);
			arr = null;
			System.out.println(arr[0]);
		} catch (ArithmeticException e) {
			System.out.println("除数不能为零");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("索引越界了");
		} catch (Exception e) { // Exception e = new NullPointerException();
			System.out.println("出错了");
		}
		System.out.println("over");
	}
}

运行结果:
除数不能为零
over

2.如果一个try语句之中同时有多个catch

捕获范围小的异常(子类异常)要放在捕获范围大的异常(父类异常)之前;
在开发中,为了简单起见,异常基本都直接使用Exception接收。
如:

public class Demo6_Exception {
   public static void main(String[] args) {
      int a = 10;  int b = 0;
      int[] arr = { 11, 22, 33, 44, 55 };
      try {
         System.out.println(a / b);
	  System.out.println(arr[10]);
      } catch (ArithmeticException e) {
           System.out.println("除数不能为零");
      } catch (ArrayIndexOutOfBoundsException e) {
           System.out.println("索引越界");
      } catch (Exception e) {	 //用超类对象接收任何子类对象		System.out.println("出错");
      }
	System.out.println("over");
   }
}

3.finally

(1):finally{} 语句增加了一个统一处理的出口操作,无论是否发生异常,程序都要执行finally {}语句。
(2):finally的作用:用于释放资源,在IO流操作和数据库操作中会见到
(3):特殊情况:在执行到finally之前,在catch中jvm退出 (System.exit(0)),此时直接从catch中退出,并不进入finally语句。

4.恶心人的地方,try…catch…finally中的return

上代码:


public class Demo8_Exception{
   public static void main(String[] args) {
	System.out.println(method());
   }
   public static int method() {
       int x = 10;
       try {
	  x = 20;
	  System.out.println(1 / 0);  
	  return x;
       } catch (Exception e) {
	  x = 30;
	  return x;
       } finally { 
	  x = 40;
	  System.out.println("finally");
	  System.out.println(x);
           //return x; //如果在这里面写返回语句,那么try和catch的结果都会被改变
       }
    }
}

运行结果是
finally
40
30

怎么来解释呢:
首先因为第二个输出的是30,这个方法的返回值肯定是30
仔细看,在try中的println发生异常后,后面的return x不会被执行;
然后到catch语句中x=30,这时候要return,但是方法不会先return,而是先执行完finally的语句
但是为什么x=40不是这个方法的返回值呢,这个先记住,(应付考试),在弄懂了之后会再写博客。
如果把最后一句的注释去掉,改成

return x;	

结果是:
finally
40
40

5.Throwable接口中的常见方法

1.getMessage():
获取异常信息,返回字符串
2.toString():
获取异常类名和异常信息,返回字符串。
3.printStackTrace():
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void


package edu.hit;

public class Demo9_Throwable {

	/**
	 * * A:Throwable的几个常见方法 
	 *     a:getMessage() 获取异常信息,返回字符串。 
	 *     b:toString()获取异常类名和异常信息,返回字符串。
	 *     c:printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
	 * B:案例演示 Throwable的几个常见方法的基本使用
	 */
	public static void main(String[] args) {
		try {
			System.out.println(1 / 0);
		} catch (Exception e) { // Exception e = new ArithmeticException("/ by zero");
			System.out.println(e.getMessage()); //获取异常信息
			System.out.println(e.toString()); //调用toString方法,打印异常类名和异常信息
			e.printStackTrace(); // jvm默认就用这种方式处理异常
		}
	}
}

运行结果
/ by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
at edu.hit.Demo9_Throwable.main(Demo9_Throwable.java:14)

6.throws的方式处理异常

throws关键字主要是用在方法的声明上,表示一个方法并不处理异常,而交给“方法的调用处”进行处理。
throws关键字除了在普通的方法上使用之外,还可以在主方法上。如果在主方法上就表示一旦出现了异常之后,继续向上抛,由JVM进行处理。
关于java基础知识的一点总结_第5张图片

7.throw和throws的区别:

throw是人为抛出
上个图把关于java基础知识的一点总结_第6张图片

8.自定义异常:

懒得说了。。。继承自Exception类,再写一些里面的方法就行了。

六、Java中的传参方式

首先要明确java中的传参是引用方式传参的,但是结合“栈指向堆”这样一种结构,会有一些时候容易在理解上出错。
有个有趣的例子嗷,详见这一篇博客

链接: link.

七、JavaIO

1.输入流和输出流与输入和输出

1.输入流是指数据源向程序输入数据,输出流是程序向数据宿输出数据
2.而输入是指的程序向文件中输入数据,输出是指从文件中向程序读出数据
(为了应对考试,这些概念上的东西就重复一点,不要嫌我啰嗦)

2.流的特点

1.每个数据都必须等待排在它前面的数据读入或送出之后才能被读写;
2.每次读写操作处理的都是序列中剩余的未读写数据中的第一个,不能随意选择输入输出的位置。(注意奥)
3.所有涉及数据流操作的程序都应该添加:import java.io

3.流的分类

(1).按处理数据单位来分

关于java基础知识的一点总结_第7张图片
1.可以分为字节流(8位二进制)和字符流(16位二进制)
2.字节流
(1)流中数据以字节为基本处理单位;
(2)字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的。
3.字符流
(1)流中数据以字符为基本处理单位(16位Unicode码);
(2)字符流只能操作纯字符数据,对字符数据操作比较方便。

(2).按角色来分

1.节点流:程序直接连接到数据源和数据宿,进行读写。
在这里插入图片描述

2.处理流:又称高级流或包装流,处理流对一个已存在的流进行连接,通过封装后的流来进行读写。
在这里插入图片描述

3.关于java基础知识的一点总结_第8张图片

4.关于java基础知识的一点总结_第9张图片

4.常用的流作用概述

关于java基础知识的一点总结_第10张图片

关于java基础知识的一点总结_第11张图片

5.InputStream类的主要方法

方法名称 作用
abstract int read() 从流中读入数据
int read(byte b[ ]) 从流中读入数据,并存放到数组b中
int read(byte b[ ],int off, int len) 从流中读入len个字节,并从数组b的off位置开始存放
long skip(long n) l跳过流中若干字节数
int available() 返回流中可用字节数
void mark(int readlimit) 在流中标记一个位置
void reset() 将流重置到标记处
boolean markSupport() 是否支持标记和复位操作
void close() 关闭流

6.关于FileInputStream类中的read()方法的一个小问题

1.首先看一些read()方法

方法名称 作用
int read() 从输入流中读取一个字节的数据,如果已到达文件末尾,则返回 -1(注意这个-1是Int型的-1,因为read()方法的返回值类型就是int类型

2.我们来看一个例子

FileInputStream fileInputStream = new FileInputStream("D:\\test.txt");
		int i;
		while((i=fileInputStream.read())!=-1) {
			System.out.println(i);	
		}

这个文件里的数是
关于java基础知识的一点总结_第12张图片
那么输出结果是
关于java基础知识的一点总结_第13张图片
可以体会到它是按字节读取的,并且是按ascll码值返回的。
2.其实在刚学的时候我是有个问题的,我在想read()方法是按byte类型来读,byte类型的值的范围是【-128,127】,那如果有些字符的ascll码值不在这个范围内那岂不是会出错,这里有这样一个表
关于java基础知识的一点总结_第14张图片
可以看到ascll可显示字符都没有超过byte类型的范围。

3.那么问题就出来了,read()方法读取的是一个字节,为何返回是int,而不是byte?
(1)首先来看一下byte类型的-1
-1的原码:10000001
反码11111110
补码11111111

(2)那么假设read()方法的返回值类型是byte,
那如果有一个序列是(随便举的一个例子)
00010100 00100100 01000001 11111111 0000000
那么读到11111111就会返回-1,导致后续的序列都读不出来
(3)所以read()方法要返回Int型,需要在读的每一个八位二进制数前面补24个0
所有遇到-1会变成00000000 00000000 00000000 11111111(这时候的值也就是255)。

7.当然,辛国栋老师讲的IO操作还有很多,小生收益很大,就不再一一列出了。

8.文件流在安卓开发上的应用

下面的代码是实现这样一个进度条操作的,有兴趣的可以看一下。
关于java基础知识的一点总结_第15张图片

Bitmap bitmap = null;
            URL url = null;
            try {
                url = new URL(strings[0]);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.connect();

                InputStream inputStream = new BufferedInputStream(url.openStream());
                OutputStream outputStream = new ByteArrayOutputStream();

                    /**
                     * 进度条的操作
                     */

                    long fileLength = conn.getContentLength();//文件总大小
                    Log.i("MainAV","文件总大小为:"+fileLength);
                    byte[] data = new byte[1024];//每次读取的大小为2的10次方个字节
                    long total = 0;//累计读取的大小
                    int count = 0;//每一次读取的大小

                    while ((count = inputStream.read(data)) != -1){
                        total+=count;
                        Log.i("MainAV","读的百分比:"+(int)(total/(float)fileLength*100));
                        publishProgress((int)(total*100/(float)fileLength));
                        outputStream.write(data,0,count);

                    }
                    //转化为字节数组
                    byte[] result = ((ByteArrayOutputStream) outputStream).toByteArray();

                    bitmap = BitmapFactory.decodeByteArray(result,0,result.length);


            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //释放资源
                inputStream.close();
                outputStream.close():

            }

            return bitmap;

八、泛型

概念就不再说了,只说一些第一次学的时候没注意到的(再次仔细看一遍书的时候总结了一下)
(1)假如有一个类用了泛型,设为Generation,在其他类(除了Generation之外)的方法中是没有办法声明Generation的,(会报错)提示你can’t resolved T to a type.,必须要把T指定为一个确定的类型(这里没有考虑通配符,马上说)。
(2)当然Generation类在被用到的时候,是可以这样声明的(不带泛型):Generation generation,这样其实就是作用(注意是作用)等同于Generation generation.
但是要注意,虽然作用等同,但是如果用Generation去接收一个(比如)Generation是会报错的,语法错误,无法通过编译。
(3)但是不带泛型是会有warning的,而且统一用Object接收让传进来的对象向上转型的话,也可能会出问题,所以引入了通配符"?"

private void fun(Generation<?> generation){

}

(4)注意这样一点,刚学的时候犯过这样错误
用ArrayList 来接收一个ArrayList,这样是会报错的。
(5)没找到合适的例子,这里有一个安卓开发中的泛型的应用。
我在用到ViewPager的时候写了这样一个PagerAdapter的基类(注意不是FragmentPagerAdapter)

package com.example.myapplication.Base;
/**
 * Created by:马俊豪
 * Description:PagerAdapter的基类
 */

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;

import java.util.ArrayList;
//android中View是所有UI的基类,所有设置泛型T extends View
public class BasePagerAdapter<T extends View> extends PagerAdapter {


    private ArrayList<T> viewArrayList;
    public BasePagerAdapter(ArrayList<T> viewArrayList){
        this.viewArrayList = viewArrayList;
    }


    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {

        View view = viewArrayList.get(position);
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(viewArrayList.get(position));
    }

    @Override
    public int getCount() {
        return viewArrayList.size();
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {

        return view==object;
    }
}

子类在继承的时候声明好T的类型就欧克了。

九、类图如何画(类之间的关系对应的线要记住)

没办法,考试是要考类图的绘制的,这里复习顺便总结一下。
这里只说类之间关系对应的类图怎么画
跟着辛国栋老师上课的同学可以在实验三的实验报告里看。
首先看类的关系:

1.继承关系

B继承A
关于java基础知识的一点总结_第16张图片

2.实现关系

类A实现接口A,这里的接口和类重名了(要注意如果类和接口在一个包里的时候,类和接口不能重名嗷,当然不在一个包里两个类,两个接口,接口和类都是可以重名的)
关于java基础知识的一点总结_第17张图片

3.依赖关系

类A用到了类B,但是关系脆弱,具有偶然性,临时性
举例:类B作为参数被类A在某个method方法中使用
在这里插入图片描述

4.关联关系

类A用到了类B,但是关系比较强
举例:表现在代码层面,为被关联类B以类的属性形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量。
关于java基础知识的一点总结_第18张图片

5.聚合关系

类Family包含类Child
关联关系的特例,has-a的关系,整体与部分。
关于java基础知识的一点总结_第19张图片

6.组合关系

类Person包含类Brain
更强的聚合,人和大脑,除了满足聚合之外,两个类的生命周期也是一样的
关于java基础知识的一点总结_第20张图片

7.单个class,interface,如何画

1.单个class
关于java基础知识的一点总结_第21张图片

(1).类名是Class,如果是虚拟类,则让Class是斜体
(2)里面的参数: 访问权限 参数名称:type = 初始值
“:type = 初始值”这一部分可以有,也可没有
(3)里面的方法:访问权限 方法名称(参数名称:参数类型 = 参数初始值):返回值类型 :返回值默认值
(4)对于访问权限:
public +
protected #
private -
default ~
2.单个Interface
关于java基础知识的一点总结_第22张图片

十、关于接口中的权限声明的问题

1.default:

如果一点也不了解的话建议自己去查一查
这里总结一下
1.接口中的default方法,实现类可以重写也可以不重写
2.实现类若继承多个接口,多个接口有两个或两个以上,那么这个接口必须重写这个default方法
3.父类重写之后。子类继承父类的时候会把这个default方法继承,而不是继承接口中的default方法

2.接口中的变量和方法都能用哪些权限词修饰(建议你一定要看看)

1.接口中只有public static final的常量,所以也必须初始化,其他都会报错,但是可以直接写 int x = 0;
这样会自动把x的权限转换成public static final,写final int x;,static int x;都会自动转换成public static final int x
但是抽象类不会自动转换,只有接口可以。
2.接口方法:
(1)不加static的时候:
只能是public或者private,(注意如果是private方法则必须有方法体,并且该方法不能是虚拟方法。其实个人的理解这里的private方法就是为了default方法服务的,相当于一个完成一部分功能的函数。)(而public方法是不能有方法体的)。
若是直接写void fun(),会默认为public abstract。
(2)加static的时候:
方法必须有方法体
有三种形式
<1>public static
<2>static(相当于public static)
<3>private static
三种都必须有方法体(显而易见,毕竟是static方法)
接口中static方法不能和final和default一起使用,普通类中可以有static final方法

就写到这里吧,基础东西的主题知识算是复习的差不多了,有些东西真的恶心啊,项目开发不会用到的,但是为了考试和以后的面试,算是尽点力吧。才疏学浅,有什么错误请指出,说不定我能多考几分呢,谢谢

你可能感兴趣的:(关于java基础知识的一点总结)