笔记区

人机交互方式

软件的出现实现了人与计算机之间更好的交互,主要的交互方式有两种:
图形化界面:这种方式简单直观,使用者易于接受,容易上手操作。
命令行方式:需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记录住一些命令。

Java语言平台版本

1) J2SE/JAVASE —- Standard Edition—-标准版/基础版
开发普通桌面和商务应用程序提供的解决方案,该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。
2) J2ME/JAVAME —- Micro Edition —- 微型版/移动版
是为开发移动设备和嵌入式设备(电器、机器人、机顶盒…)提供的解决方案。
3) J2EE/JAVAEE —- Enterprise Edition—- 企业版/商务版
是为开发企业环境下的应用程序提供的一套解决方案,主要针对于企业级应用程序开发。

Java语言特性

原理是什么?
不同的操作系统都有与之对应的JVM,只要在需要运行java应用程序的操作系统上,安装一个JVM,由JVM来负责Java程序在该系统中的运行。所以只需要写一个Java程序,就可以在多个不同的操作系统上执行。这样就实现了Java程序的跨平台性。也称为Java具有良好的可移植性。
注意JVM是Java语言能够跨平台的前提,但是JVM本身不跨平台

JDK是整个java开发的核心,它包含了:

  1. JAVA开发工具(jdk\bin)
    2. 基础开发库(jdk\jre\lib\rt.jar)
    3. 基础开发库的源码(jdk\src.zip)

注意事项:
1) 同时安装多个JDK时需要使用执行环境变量来确认使用的是哪个jdk
2) 安装时选择默认选项安装到默认目录即可,即: C:\Program Files\Java\jdk1.8.0_191
3) 注意安装路径不要有中文或者特殊符号,比如空格等,最好目录统一

标识符

标识符可以简单的理解成一个名字。在Java中,我们需要标识代码的很多元素,包括类名、方法、字段、变量、包名等等。我们选择的那个名称就称为标识符,一个正确的标识符需要遵循以下规则:
1) 标识符可以由字母、数字、下划线(_)、美元符($)组成,但不能包含 @、%、空格等其它特殊字符
2) 不能以数字开头。如:123name不合法
3) 标识符严格区分大小写。如:tmooc 和 Tmooc是两个不同的标识符
4) 标识符的命名最好能反映出其作用,做到见名知意。
5) 标识符不能是Java的关键字

ASCII编码表

ASCII(American Standard Code for Information Interchange)编码表,美国标准信息交换代码。
在计算机中,所有的数据在存储和运算时都要使用二进制数表示。
a、b、c、d这样的52个字母(包括大写)、以及0、1等数字还有一些常用的符号, 在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码),而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则。
于是美国有关的标准化组织就出台了ASCII编码,统一规定了上述常用符号用哪些二进制数来表示。
中国** gb2312【字少】 àgbk【识别4+汉字】à万国码表unicodeISO**制定】
所有码表都兼容**ASCALL
:ASCII码表**

for概述

循环结构是指在程序中需要反复执行某个功能而设置的一种程序结构。
它由循环体中的条件,判断继续执行某个功能还是退出循环。
根据判断条件,循环结构又可细分为先判断后执行的循环结构和先执行后判断的循环结构。

嵌套for概述

存在至少2层for循环,根据外层的条件,判断里层能否执行
如果能执行,就把里层代码都循环完毕后,再继续判断是否执行外层循环的下一轮循环

break与continue

break: 直接结束当前循环,跳出循环体,简单粗暴
TIPS: break以后的循环体中的语句不会继续执行,循环体外的会执行
continue: 跳出本轮循环,继续下一轮循环
TIPS:continue后本轮循环体中的语句不会继续执行,但是会继续执行下轮循环,循环体外的也会执行

局部变量

  1. 位置:定义在方法里或者局部代码块中<br />注意:必须手动初始化来分配内存.如:int i = 5;或者int i; i = 5;<br />作用域:也就是方法里或者局部代码块中,方法运行完内存就释放了

成员变量

  1. 位置:定义在类里方法外<br /> 注意:不用初始化,也会自动被初始化成默认值<br /> 作用域:整个类中,类消失了,变量才会释放

三种循环的区别

1.如果条件判断从来没有满足过,那么for循环和while循环将会执行0次,但是do-while循环会执行至少一次。
2.for循环的变量在小括号当中定义,只循环内部才可以使用。while循环和do-while循环初始化语句本来就在外面,所以出来循环之后还可以继续使用。

方法

方法定义格式

  1. public class void 方法名称(){
  2. 方法体
  3. }

调用格式
方法名称();
注意事项:
1.方法定义的先后顺序无所谓。
2.方法定义必须是挨着的,不能在一个方法的内部定义另一个方法。
3.方法定义之后,自己不会执行,要执行,就得进行方法调用
方法的三种调用格式:
1.单独调用:方法名称(参数);
2.打印调用:System.out.println(方法名称(参数));
3.赋值调用:数据类型 变量名称 = 方法名称(参数);

  1. public static void main(String[] args) {
  2. //单独调用
  3. sum(15,25);
  4. System.out.println("===========");
  5. //打印调用
  6. System.out.println(sum(20, 15));
  7. System.out.println("============");
  8. //赋值调用
  9. int number = sum(11, 20);
  10. System.out.println(number);
  11. }
  12. public static int sum(int a, int b) {
  13. System.out.println("方法执行!");
  14. int result = a + b;
  15. return result;
  16. }

比较两数字是否相同:

  1. public static void main(String[] args) {
  2. System.out.println(sum(10, 15));
  3. System.out.println(sum(10, 10));
  4. }
  5. public static boolean sum(int a, int b) {
  6. // boolean same;
  7. // if (a == b) {
  8. // same = true;
  9. // }else {
  10. // same = false;
  11. // }
  12. // boolean same = a == b ? true : false;
  13. // boolean same = a == b;
  14. return a == b;
  15. }
  16. }

求出1到100的累加和:

  1. public static void main(String[] args) {
  2. System.out.println(sum());
  3. }
  4. public static int sum() {
  5. int sum = 0;
  6. for (int i = 1; i <= 100; i++) {
  7. sum += i;
  8. }
  9. return sum;
  10. }

方法重载

A.与下列因素有关:
1.参数个数不同
2.参数类型不同
3.参数的多类型顺序不同

B.与下列因素无关
1.与参数的名称无关
2.与方法的返回值类型无关

数组

数组概念:
是一种容器,可以同时存放多个数据值。
数组特点:
1.数组是一种引用数据类型。
2.数组当中的多个数据,类型必须统一。
3.数组的长度在程序运行期间不可改变。
两种常见的数组初始化方式:
1.动态初始化(指定长度)
2.静态初始化(指定内容)
动态初始化数组的格式:
数据类型[ ] 数组名称 = new 数据类型[数组长度];
静态初始化数组的格式:
1.数据类型[ ] 数组名称 = new 数据类型[ ]{元素1,元素2,元素3,……};
静态数组省略格式:
2.数据类型[ ] 数组名称 = {元素1,元素2,元素3,……};

使用建议:如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体内容,用静态初始化。

图片识别

求出数组中的最大值:

  1. public static void main(String[] args) {
  2. int[] array = {5,15,30,28,10000};
  3. int max = array[0];
  4. for (int i = 0; i < array.length; i++) {
  5. if (array[i] > max) {
  6. max = array[i];
  7. }
  8. }
  9. System.out.println("最大值" + max);
  10. }

求出数组中的最小值:

  1. public static void main(String[] args) {
  2. int[] array = {5,15,30,28,10000};
  3. int min = array[0];
  4. for (int i = 0; i < array.length; i++) {
  5. if (array[i] < min) {
  6. min = array[i];
  7. }
  8. }
  9. System.out.println("最小值" + min);
  10. }

数组元素反转:

  1. public static void main(String[] args) {
  2. int[] array = {1,2,3,4,5};
  3. for (int i = 0; i < array.length; i++) {
  4. //遍历打印数组本来的样子
  5. System.out.print(array[i]);
  6. }
  7. System.out.println();
  8. /**
  9. * 初始化语句: int min = 0; max = array.length - 1
  10. * 条件判断: min < max;
  11. * 步进表达式: min++, max--
  12. * 循环体: 用第三个变量倒手
  13. */
  14. for (int min = 0,max = array.length-1; min < max; min++,max--) {
  15. int t = array[min];
  16. array[min] = array[max];
  17. array[max] = t;
  18. }
  19. for (int i = 0; i < array.length; i++) {
  20. //再次打印遍历数组后来的样子
  21. System.out.print(array[i]);
  22. }

数组作为方法返回值_返回地址:

  1. public class Demo1 {
  2. public static void main(String[] args) {
  3. int[] result = calculate(10, 20, 15);
  4. System.out.println("result方法内部数组是:");
  5. System.out.println(result);
  6. System.out.println("总和:" + result[0]);
  7. System.out.println("平均数:" + result[1]);
  8. }
  9. public static int[] calculate(int a,int b,int c) {
  10. int sum = a+b+c;
  11. int avg = sum/3;
  12. // int array = new int[2];
  13. // array[0] = sum;//总和
  14. // array[1] = avg;//平均数
  15. int[] array = {sum,avg};
  16. System.out.println("calculate方法内部数组是:");
  17. System.out.println(array);
  18. return array;
  19. }
  20. }
  21. /*
  22. *运行结果如下:
  23. *calculate方法内部数组是:
  24. *[I@15db9742
  25. *result方法内部数组是:
  26. *[I@15db9742
  27. *总和:45
  28. *平均数:15
  29. */

拓展

  1. public static void main(String[] args) {
  2. int[] array = {1,2,3,4,5,6};
  3. System.out.print("[");
  4. for (int i = 0; i < array.length; i++) {
  5. if (i == array.length-1) {
  6. System.out.print(array[i] + "]");
  7. }else {
  8. System.out.print(array[i] + ", ");
  9. }
  10. }//上面程序打印出来和数组的样式一样
  11. System.out.println();
  12. System.out.println(Arrays.toString(array));
  13. }

遍历输出数组中的偶数int[] arr = {1,2,3,4,5,6}

For(int i = 0;i<arr.length;i++){ if(arr[i]%2==0){
System.out.println(arr[i]);
}
}

简述分支结构和循环结构在什么时候应用

答案:分支结构解决是否的问题,循环结构解决反复执行的问题

简述驼峰规则

在JAVA中,驼峰规则一般是标识符用来命名变量、方法,主要是对多单词的标识符——第一个单词首字母为小写,其他单词首字母为大写

简单讲一下Java跨平台的原理

java源程序(.java文件)通过编译器编译成为Class文件(字节码文件),而它的class文件是基于字节码(以byte为单位存储的文件)的,而字节码文件是描述程序要运行的的虚指令的集合,这些虚指令的集合与任何的平台无关,Java虚拟机认识它(只要在不同的平台下部署相应的jre,运行jvm!就可以了)

Java 语言是以类为程序的基本单位的

以下构造的描述**错误**的是 D
A 构造方法是新建对象时执行的一个特殊方法
B 构造一个对象之后,立即执行的一个方法
C 一个类,必须有构造方法
D 如果自己不定义,编译器不会添加默认构造方法
this.xxx的讲述**错误**的是 D
A this 特殊引用,引用当前对象的地址
B this.xxx 调用成员
C 当有重名局部变量,必须用this.xx调用成员变量
D this.xxx就是xxx是当前变量值
A 重载是面向对象的一个基本特性
B 重载就是在一个类中,有相同的方法名称,但形参不同的方法
C 重载的结果,可以让一个程序段尽量减少代码和方法的种类。
D 跟成员方法一样,构造方法不可以重载
分析选项中关于Java中this关键字的说法正确的是 A
A this关键字是在对象内部指代自身的引用
B this关键字可以在类中的任何位置使用
C this关键字和类关联,而不是和特定的对象关联
D 同一个类的不同对象共用一个this

谈谈java跟你所知道的其它的语言相比,有什么优点?

答案:1.跨平台性,虽然是很好的优势,可以让JAVA在任何的系统中运行,但是前提是该系统要安装JAVA虚拟机,这样导致一些JAVA编写的桌面程序无法在一般的用户
2.JAVA的身后是SUN公司,提供及时的API更新,但是过多的版本导致JAVA的向下兼容性很差。
3.面向对象基于面向过程,Java是面向对象语言,它适合BS系统,相对于底层底层程序无法同C++抗衡

说说重载和重写的区别

Overload是重载的意思,表示在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可,
Override是覆盖的意思,也就是重写,在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,
两者不同主要体现在:目的不同、范围不同、参数不同、多态性不同、返回类型不同。
1、目的不同
overload用于增加程序的可读性(做法不同,但是做的同一事情)。
override用于提供其超级类已经提供的方法的特定实现。
2、范围不同
overload 在相同的类范围内内执行。
override发生在两类具有继承(继承)的关系。
3、参数不同
overload参数必须不同。
override参数必须相同。

==和equals的区别

1.当使用==比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等。
2.当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
众所周知,任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。

StringBuilder和StringBuffer的区别

1.在线程安全上 :
—StringBuffer是旧版本就提供的,线程安全的。@since JDK1.0
—StringBuilder是jdk1.5后产生,线程不安全的。@since 1.5
2. 在执行效率上,StringBuilder > StringBuffer > String
3.源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。
abstract class AbstractStringBuilder implements Appendable, CharSequence {

String

  • 常见方法
    • length()-查看字符串的长度
    • charAt()获取下标为某的char字符
    • concat(“cxy”)在原有的字符串上进行拼接,注意不改变原来的串
    • substring()-截取子串,如果参数有两个左闭右开[1,5)
    • equals()-判断两个串是否相等,注意String重写了Object的此方法,所以内容相同就返回true
    • startsWith()-判断是不是以参数开头
    • endsWith()—判断是不是以参数结尾
    • split()—以指定字符分割
    • trim()-去掉首尾两端的空格
    • getBytes()-把串转换成数组
    • toUpperCase()-变成全大写
    • toLowerCase()-变成全小写
    • String.valueOf(10)-把int类型的10转换成String类型
    • indexOf(“c”)获取c字符在字符串中第一次出现的索引值
    • lastIndexOf(“c”)获取获取c字符在字符串中最后一次出现的索引值

abstract注意事项

抽象方法要求子类继承后必须重写。
那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
1) private:被私有化后,子类无法重写,与abstract相违背。
2) static:静态优先于对象存在。而abstract是对象间的关系,存在加载顺序问题。
3) final:被final修饰后,无法重写,与abstract相违背。

1.类与类的关系

  1. --继承关系,只支持单继承<br /> --比如,A是子类 B是父类,A具备B所有的功能(除了父类的私有资源和构造方法)<br /> --子类如果要修改原有功能,需要重写(方法签名与父类一致 + 权限修饰符>=父类修饰符)<br />

2.类和接口的关系

  1. --实现关系.可以单实现,也可以多实现<br /> --class A implements B,C{}<br /> --其中A是实现类,BC是接口,A拥有BC接口的所有功能,只是需要进行方法的重写,否则A就是抽象类<br />

3.接口与接口的关系

  1. --是继承关系,可以单继承,也可以多继承<br /> --interface A extends B,C{}<br /> --其中ABC都是接口,A是子接口,具有BC接口的所有功能(抽象方法)<br /> --class X implements A{}<br /> --X实现类需要重写ABC接口的所有方法,否则就是抽象类<br /> --class A extends B implements C,D{}<br /> --其中A是实现类,也是B的子类,同时拥有CD接口的所有功能<br /> --这时A需要重写CD接口里的所有抽象方法

4.抽象类与接口的区别

  1. --抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)<br /> --接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法<br /> --接口会为方法自动拼接public abstract,还会为变量自动拼接public final static<br /> --抽象类可以有构造方法--用来给子类创建对象,接口中没有构造方法<br /> --抽象类和接口都不能实例化(创建对象)<br /> --抽象类可以有普通方法,接口都是抽象方法<br /> <br />**接口里****没有成员变量,都是常量****。所以,你定义一个变量没有写修饰符时,默认会加上:public static final**

接口里是没有构造方法的**
在创建实现类的对象时默认的super(),是调用的默认Object的无参构造。**

方法

方法的修饰符** 方法的返回值 方法名([参数列表…]){**方法体;}
public static void main(String[] args){ …. }

方法的重载

方法的重载是指在一个类中定义多个同名的方法,但是每个方法的参数列表不同(也就是指参数的个数和类型不同),程序在调用方法时,可以通过传递给他们的不同个数和类型的参数来决定具体调用哪个方法.

面向对象

概念

面向对象其实是一种编程思想,通过它可以把生活中复杂的事情变得简单化,从原来的执行者变成了指挥者。
面向对象是基于面向过程而言的。
面向过程强调的是过程,比如:
1. 打开冰箱门 2. 把大象放进去 3. 关上冰箱门
面向对象强调的是结果,比如:
什么样的冰箱?什么样的大象?谁负责把大象装进去? 而不是关注那个负责的人怎么把大象装冰箱里.
衣服脏了,直接让女盆友去处理,等着穿干净的就可以了。你不关注中间的过程,只要找好对象就可以了~
再比如.我们想吃一道菜,无需考虑是怎么传菜,怎么做菜的,只需点菜即可.传菜和做菜都有具体的对象来帮我们完成具体的功能.我们不需要关注实现的过程,只需要关注结果就好
这就是我们所说的面向对象的编程实现(OOP,Object Oriented Programming)

面向对象的三大特征

1) 封装性,把相关的数据封装成一个“类”组件
2) 继承性,是子类自动共享父类属性和方法,这是类之间的一种关系
3) 多态,增强软件的灵活性和重用性

TIPS:**如何封装?封装后的资源如何访问**?
我们可以使用private关键字来封装成员变量与方法
如何访问私有资源?
关于成员变量:
1. setXxx – 对外提供公共的设置值方式
2. getXxx – 对外提供公共的获取值方式
关于成员方法:
把私有方法放在公共方法里供外界调用即可

构造方法

概念

构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型的方法
对象创建就是通过构造方法完成的,主要功能是完成对象的创建或者对象的初始化
当类创建对象(实例化)时,会自动调用构造方法
构造方法与普通方法一样也可以重载.

形式

与类同名,且没有返回值类型,可以含参也可以不含参
修饰符** 方法名([参数列表]){ 注意:方法名与类名一样
**代码…..
}

TIPS:关于构造函数怎么记忆
特点:方法名与类名相同,且没有返回值类型
执行时机:创建对象时立即执行
默认会创建无参构造,但是,如果自定了含参构造,默认的无参构造会被覆盖,注意要手动添加哦

构造代码块的特点

1) 位置: 在类的内部,在方法的外部
2) 作用: 用于抽取构造方法中的共性代码
3) 执行时机: 每次调用构造方法前都会调用构造代码块
4) 注意事项: 构造代码块优先于构造方法加载

局部代码块

1) 位置: 在方法里面的代码块
2) 作用: 通常用于控制变量的作用范围,出了花括号就失效
3) 注意事项: 变量的作用范围越小越好,成员变量会存在线程安全的问题

* 总结:
1.当创建对象时,程序会自动调动构造方法,但是如果有构造代码块,会先去执行构造代码块,再执行构造方法
2.当通过对象调用方法时,会执行方法中的功能,如果方法中有局部代码块,就会执行局部代码块
3.执行顺序: 构造代码块—>构造方法—>局部代码块[前提:调用方法(如果方法有局部代码块,局部代码块才会执行)]
4.构造代码块的功能: 用于提取构造方法中的共性
5.局部代码块的功能:控制变量的作用范围
*/

继承

特1) 使用extends关键字来表示继承关系

2) 相当于子类把父类的功能复制了一份
3) Java只支持单继承
4) 继承可以传递(爷爷/儿子/孙子这样的关系)
5) 不能继承父类的私有成员
6) 继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
7) 像是is a的关系

方法重写Override

1) 继承以后,子类就拥有了父类的功能
2) 在子类中,可以添加子类特有的功能,也可以修改父类的原有功能
3) 子类中方法的签名与父类完全一样时,会发生覆盖/复写的现象
4) 格式要求:方法的返回值 方法名 参数列表 要完全一致,就方法体是重写的
TIPS: 父类的私有方法不能被重写,子类在重写父类方法时,修饰符
子类重写父类方法时,子类修饰符要大于等于父类修饰符的权限

this与super的区别

1) This代表本类对象的引用
class Father3{ this.XXX } //this — Father3 this = new Father3();
2) super代表父类对象的引用
class Father3{ super.XXX } //this — Father3 super = new Father3();
就相当于创建了一个父类对象
3) this可以在两个变量名相同时,用于区分成员变量和局部变量
4) this 可以在本类的构造方法之间调用,位置必须是第一条语句,注意,不能相互调用,会死循环
5) super是发生了继承关系以后,子类如果想用父类的功能,可以通过super调用
6) 如果发生了重写,还想用父类的功能,需要使用super来调用
7) Super在调用父类构造方法时,必须出现在子类构造方法的第一条语句,而且如果父类中没有提供无参构造,子类可以通过super来调用父类其他的含参构造

重载Overload 与重写Override的区别

1) 重载: 是指在一个类中的现象,是指一个类中有很多同名的方法,但是方法的参数列表不同
2) 重写: 是指发生了继承关系以后(两个类),子类去修改父类原有的功能,子类中有一个方法签名(返回值类型 方法名(参数列表) )和父类的一模一样
3) 重载的意义: 是为了方便外界对方法进行调用,什么样的参数程序都可以找到对应的方法来执行,体现的是程序的灵活性
4) 重写的意义:是在不修改源码的前提下,进行功能的修改和拓展
(OCP原则:面向修改关闭,面向拓展开放)

static

特点
1) 可以修饰成员变量与成员方法
2) 随着类的加载而加载,优先于对象加载
3) 只加载一次,就会一直存在,不再开辟新空间, 直到类消失才一起消失
4) 静态资源也叫做类资源,全局唯一,被全局所有对象共享
5) 可以直接被类名调用
6) 静态只能调用静态,非静态可以随意调用
7) static不能和this或者super共用,因为有static时可能还没有对象

三种代码块的比较

1) 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
2) 构造代码块:在创建对象时会自动调用,每次创建对象都会被调用,提取构造共性
3) 局部代码块:方法里的代码块,限制局部变量的范围

结论:执行顺序:静态代码块 —> 构造代码块 —> 构造方法 —> 局部代码块

final

特点
1) 被final修饰的类,不能被继承
2) 被final修饰的方法,不能被重写
3) 被final修饰的变量是个常量,值不能被改变
4) 常量的定义形式:final 数据类型 常量名 = 值

多态

多态指同一个实体同时具有多种形式

特点
1) 多态的前提1:是继承
2) 多态的前提2:要有方法的重写
3) 父类引用指向子类对象,如:Animal a = new Cat();
4) 多态中,编译看左边,运行看右边

多态的好处

1) 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
2) 提高了程序的可扩展性和可维护性

多态的使用

特点
1) 成员变量: 使用的是父类的
2) 成员方法: 由于存在重写现象,所以使用的是子类的
3) 静态成员: 随着类的加载而加载,谁调用就返回谁的

  1. ** /******注意!!!静态资源属于类,不存在重写现象,只是两个类中有同样声明的方法而已,不属于重写*/**

静态变量和实例变量的区别

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

异常的继承结构

Throwable : 顶级父类
—Error : 系统错误,无法修复
—Exception : 可以修复的错误
— RunTimeException
— ClassCastException
— ClassNotFoundException

异常处理

当程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出
当一个方法抛出异常,调用位置可以不做处理继续向上抛出,也可以捕获处理异常

总结7:如果还有上述两种异常之外的异常,用Exception匹配捕获
这个就是多态最为经典的一种用法,我们不关心子类的子类
只要是可解决的异常,都是Exception的子类,多态会把这些异常当做父类型来看
* 进而捕获,使用通用异常解决方案来解决

抽象方法的格式

权限修饰符 abstract 返回值类型 方法名(参数列表);

抽象类特点

  1. 1) abstract 可以修饰方法或者类<br /> 2) abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法<br /> 3) 抽象类中可以没有抽象方法<br /> 4) 如果类中有抽象方法,那么该类必须定义为一个抽象类<br /> 5) 子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写<br /> 6) 多用于多态中<br /> 7) 抽象类不可以被实例化

抽象类中的构造函数通常在子类对象实例化时使用

总结**:*
1.抽象类中可以有构造方法
2.父类的构造方法要优先于子类执行
3.抽象类不可以创建对象(实例化)
4.抽象类中存在的构造方法不是为了创建本类对象时调用
而是为了创建子类对象时使用

/1.抽象类中可以有成员变量吗?—可以!!!*/
/
2.抽象类中可以有成员常量吗?—可以!!!/
/**3.抽象类中可以有普通方法吗?—可以!!!
抽象类中可以都是普通方法吗?—可以!!
/4.如果一个类中都是普通方法,为啥还要被声明成抽象类呢?
原因:抽象类不可以创建对象
如果不想让外界创建本类对象,可以把普通类声明成抽象类
/
5.抽象类中可以有抽象方法
一旦类中有抽象方法,这个类必须被声明成一个抽象类/
6.当一个类继承了父类,并且父类是抽象父类时
子类需要重写(实现)父类中的所有抽象方法或者把自己变成抽象子类
/

IO的继承结构

1. **主流分类
1) 按照方向进行分类:输入流 输出流(相对于程序**而言,从程序写数据到文件中是输出)
2) **按照传输类型进行分类:字节流 字符流
3) **组合: 字节输入流 字节输出流 字符输入流 字符输出流
2. **学习方法:在抽象父类中学习通用的方法,在子类中学习如何创建对象**

3.字节输入流:

—InputStream 抽象类,不能new,可以作为超类,学习其所提供的共性方法
—FileInputStream 子类,操作文件的字节输入流,普通类
—BufferedInputStream 子类,缓冲字节输入流,普通类

4.字符输入流

—Reader 抽象类,不能new,可以作为超类,学习其所提供的共性方法
—FileReader,子类,操作文件的字符输入流,普通类
—BufferedReader,子类,缓冲字符输入流,普通类

5.字节输出流:

—OutputStream 抽象类,不能new,可以作为超类,学习其所提供的共性方法
—FileOutputStream 子类,操作文件的字节输出流,普通类
—BufferedOutputStream 子类,缓冲字节输出流,普通类

6.字符输出流

—Writer 抽象类,不能new,可以作为超类,学习其所提供的共性方法
—FileWriter,子类,操作文件的字符输出流,普通类
—BufferedWriter,子类,缓冲字符输出流,普通类

线程生命周期,主要有五种状态:

1) 新建状态(New) : 当线程对象创建后就进入了新建状态.如:Thread t = new MyThread();
2) 就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即为进入就绪状态.
处于就绪(可运行)状态的线程,只是说明线程已经做好准备,随时等待CPU调度执行,并不是执行了t.start()此线程立即就会执行
3) 运行状态(Running):当CPU开始调度处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态
注意:就绪状态是进入运行状态的唯一入口,也就是线程想要进入运行状态状态执行,先得处于就绪状态
4) 阻塞状态(Blocked):处于运状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行.
5) 根据阻塞状态产生的原因不同,阻塞状态又可以细分成三种:
a) 等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态
b) 同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态
c) 其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态.当sleep()状态超时.join()等待线程终止或者超时或者I/O处理完毕时线程重新转入就绪状态
6) 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

测试多线程的创建方式1

  1. //这个类用来测试多线程售票
  2. //需求:设计4个售票窗口,总计售票100张
  3. public class Test4_SaleTickets2 {
  4. public static void main(String[] args) {
  5. //3.创建对象
  6. TicketRunnable target = new TicketRunnable();
  7. Thread thread = new Thread(target);
  8. Thread thread2 = new Thread(target);
  9. Thread thread3 = new Thread(target);
  10. Thread thread4 = new Thread(target);
  11. //4.启动线程
  12. thread.start();
  13. thread2.start();
  14. thread3.start();
  15. thread4.start();
  16. }
  17. }
  18. //1.创建多线程类
  19. class TicketRunnable implements Runnable{
  20. static int tickets = 100; //创建变量,记录票的总数
  21. //2.把业务放入run()
  22. @Override
  23. public void run() {
  24. while(true) {//一直卖票
  25. //假设当前tickets=1
  26. if(tickets>0) {
  27. try {
  28. //先让程序休眠10ms
  29. //问题1:超卖,0 -1
  30. //问题2:重卖,70号票卖给了两个人
  31. Thread.sleep(10);//线程访问的延迟性
  32. } catch (InterruptedException e) {
  33. e.printStackTrace();
  34. }
  35. //Thread.currentThread().getName()获取当前正在执行任务的线程名
  36. System.out.println(Thread.currentThread().getName()+"="+tickets--);
  37. }
  38. if(tickets<=0) break;//死循环的出口!!
  39. }
  40. }
  41. }

多线程创建2:实现Runnable接口

  1. //这个类用来测试多线程售票
  2. //需求:设计4个售票窗口,总计售票100张
  3. public class Test4_SaleTickets2 {
  4. public static void main(String[] args) {
  5. //3.创建对象
  6. TicketRunnable target = new TicketRunnable();
  7. Thread thread = new Thread(target);
  8. Thread thread2 = new Thread(target);
  9. Thread thread3 = new Thread(target);
  10. Thread thread4 = new Thread(target);
  11. //4.启动线程
  12. thread.start();
  13. thread2.start();
  14. thread3.start();
  15. thread4.start();
  16. }
  17. }
  18. //1.创建多线程类
  19. class TicketRunnable implements Runnable{
  20. static int tickets = 100; //创建变量,记录票的总数
  21. //2.把业务放入run()
  22. @Override
  23. public void run() {
  24. while(true) {//一直卖票
  25. //假设当前tickets=1
  26. if(tickets>0) {
  27. try {
  28. //先让程序休眠10ms
  29. //问题1:超卖,0 -1
  30. //问题2:重卖,70号票卖给了两个人
  31. Thread.sleep(10);//线程访问的延迟性
  32. } catch (InterruptedException e) {
  33. e.printStackTrace();
  34. }
  35. //Thread.currentThread().getName()获取当前正在执行任务的线程名
  36. System.out.println(Thread.currentThread().getName()+"="+tickets--);
  37. }
  38. if(tickets<=0) break;//死循环的出口!!
  39. }
  40. }
  41. }

List接口

有序的colletion(也称为序列).此接口的用户可以对列表中的每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素.
1. 元素都有下标
2. 数据是有序的
3. 允许存放重复的元素

Set接口

  1. 数据无序且数据不允许重复
    2. HashSet : 底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
    3. TreeSet : 底层是TreeMap,也是红黑树的形式,便于查找数据

    HashSet

    底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K存入内部的HashMap中,其中K不允许重复,允许使用null.

    Map

  2. Map可以根据键来提取对应的值
    2. Map的键不允许重复,如果重复,对应的值会被覆盖
    3. Map存放的都是无序的数据
    4. Map的初始容量是16,默认的加载因子是0.75

    HashMap

    前言:HashMap的键要同时重写hashCode()和equlas()
    hashCode()用来判定二者的hash值是否相同,重写后根据属性生成
    equlas()用来判断属性的值是否相同,重写后,根据属性判断
    —equlas()判断数据如果相等,hashCode()必须相同
    —equlas()判断数据如果不等,hashCode()尽量不同
    概述:HashMap底层是一个Entry[ ]数组,当存放数据时,会根据hash算法来计算数据的存放位置
    算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量
    当计算的位置没有数据的时候,会直接存放数据
    当计算的位置,有数据时,会发生hash冲突/hash碰撞,解决的办法就是采用链表的结构,在对应的数据位置存放链表的头节点,对于这个链表来说,每次新加的节点会从头部位置开始加入,也就是说,数组中的永远是新节点.

线程的其他创建方式

/7.线程池ExecutorService:用来存储线程的池子,把新建线程/启动线程/关闭线程的任务都交给池来管理*/
/
8.Executors用来辅助创建线程池对象,newFixedThreadPool()创建具有参数个数的线程数的线程池/
ExecutorService pool = Executors.newFixedThreadPool(5);
for(int i = 0;i<5;i++) {
/**9.excute()让线程池中的线程来执行任务,每次调用都会启动一个线程
/
pool.execute(target);//本方法的参数就是执行的业务,也就是实现类的目标对象
}
}

单例设计模式

单例模式最重要的是确保对象只有一个。
简单来说,保证一个类在内存中的对象就一个。

* 思考:对象创建好并且用公共的方式返回,那么此公共方法外界该如何调用呢?

  1. * 之前我们都是在外部创建好本类对象进行调用的,但是现在外界无法创建本类对象<br /> * 解决方案:我们可以利用之前学习的静态的概念,被static关键字修饰的资源可以通过类名直接调用<br /> */

* 问题:程序中有共享资源single,并且有多条语句(3句)操作了共享资源

  1. * 此时single共享资源一定会存在多线程数据安全问题<br /> * 解决方案:加同步锁-同步代码块-同步方法[由于方法中的所有代码都被同步了,所以可以直接变成同步方法]<br /> * 锁的位置:操作共享资源的多条语句<br /> * 锁对象:static中不能使用this & 外部创建了obj,注意是static

/*同步代码块:静态区域内,不能使用this关键字,因为静态资源优先于对象this加载
因为静态资源属于类资源,随着类的加载而加载,而this指的是本类对象*/

//总结:
//1.延迟加载的思想:是指不会在第一时间就把对象创建好来占用内存,而是什么时候需要用到,什么时候才去创建
//2.线程安全问题:是指共享资源有线程并发的数据隐患,可以通过加锁的方式[同步代码块/同步方法]
//饿汉式与懒汉式的区别:
//饿汉式是不管你用不用这个类的对象,先帮你创建一个
//懒汉式是先不给你创建这个类的对象,等你需要时再帮你创建—延迟加载的思想

线程常用方法

1.start():启动当前线程,调用当前线程的run()
2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
3.currentThread():静态方法,返回执行当前的线程
4.getName():获取当前线程的名字
5.setName():设置当前线程的名字
6.yield():释放当前cup的执行权
7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,
线程b才结束阻塞状态。
8.stop():已过时。当执行此方法时,强制结束当前线程。
9.sleep(long millitime):让当前线程”睡眠”指定millitime毫秒.在指定的millitime毫秒
时间内,当前线程是阻塞状态
10.isAlive():判断当前线程是否存活

Java的调度方法

同优先级线程组成先进先出队列(先到先服务), 使用时间片策略
对高优先级, 使用优先调度的抢占式策略

线程的优先级:

  • 1.
    MAX_PRIORITY:10
    MIN_PRIORITY:1
    NORM_PRIORITY:5

    2.
    如何获取和设置当前线程的优先级?
    getPriority():获取线程的优先级
    setPriority(int p):设置线程的优先级

    说明:高优先级的线程要抢占低优先级线程CPU的执行权,但是只是从概率上讲,
    高优先级的线程高概率的情况下被执行. 并不意味着只有当高优先级的线程执行完以后,
    低优先级的线程才会执行.