标识符、HelloWorld
/*
标识符
Java中,自己定义的内容
标识符的规则:
组成: 字母52个A-Z a-z 数字0-9 _ 下划线 $ 美元符
注意: 不能数字开头,不能是关键字
定义名字:
_abc 0a a0 a#a a$a void
YES NO YES NO YES NO
类的名字: 首字母大写,第二个单词首字母大写
BeiJingShiHaiDianQuYiYuan
MeiGuoJiaLiFuNiYa
方法的名字:首字母小写,每个单词首字母大写
addStudent
*/
public class Demo{
public static void main(String[] args) {
int _Class;
}
}
/*
实现了一个Java的HelloWorld程序
实现步骤:
1. 定义类
2. 定义主方法
3. 一条命令,控制台输出了HelloWorld
*/
public class HelloWorld{
//main主方法,固定格式,程序的入口点
public static void main(String[] args){
//系统 输出 打印 打印的内容
System.out.println("HelloWorld");
}
}
变量、数据类型、运算符
1.什么是变量?变量的定义格式?要使用变量需要注意什么?
就是可变的量
数据类型 变量名 = 数值;
同一范围内不能重复定义
不赋值不能使用
2.Java中的数据类型分几类?基本数据类型有哪些?
两大类
基本数据类型
byte(1) short(2) int(4) long(8) float(4) double(6) char(2) boolean(1)
引用数据类型
类 接口 数组 枚举
3.数据类型转换:
隐式转换:由低级专向高级
强制转换:由高级专向低级
面试题:
第一题:
byte b1=3,b2=4,b;
b=b1+b2;//错误 因为他们最终是要转向int类型 而int类型的值不能赋值给byte
b=3+4;//正确 因为他们都是常量 具有常量类型优化机制 可以直接识别为byte
哪句是编译失败的呢?为什么呢?
第二题:
byte by = 130;有没有问题?有问题如何解决?结果是多少呢?
有问题 因为这个数超出了byte的取值范围 要用byte类型进行强制转换 结果是-126
第三题:
byte b = 10;
b++;
b = b + 1;//失败 因为在和一个int类型的常量进行相加的时候b自动转换成int类型 而一个int类型的数据是没办法直接赋值给byte类型的变量的
哪句是编译失败的呢?为什么呢?
4.常见的算术运算符有哪些?
答:+ - * / %
(1)+运算符的作用有哪些?
可以作为数学运算符 也可用作字符串拼接符
(2)除法和取余的区别?
除法是数学运算机型相初操作 取余数运算符是对除法操作之后取其余数进行操作的
(3)++和–的使用规则?
分别为自增 自减 在放在 变量前面就是先进行运算放在后面就是后进行运算
5.常见的赋值运算符有哪些?
答:= += -= *= /= %=
(1)+=运算的作用是什么?
a += b;== a = a + b;
(2)扩展的赋值运算符有什么特点?
会进行自动强制数据类型转换
6.看程序说结果,请不要提前运行?
public class Test1 {
public static void main(String[] args) {
int x = 4;
int y = (--x)+(x--)+(x*10);//26
System.out.println("x = " + x + ",y = " + y);
}
}/*x = 2 y = 26*/
基本数据类型包装类,装箱、拆箱
包装类
把基本数据类型成员变量看作对象可以进行一些操作
int->Integer
byte->Byte
……
装箱、拆箱
JDK1.5后出现的新特性,自动装箱和自动拆箱
自动装箱:基本数据类型,直接变成对象
Integer in = 1;//Integer in = new Integer(1)
自动拆箱:对象中的数据变回基本数据类型
in = in + 1;//in = in.inValue + 1
为循环起名、使用引用数据类型(Random、Scanner)
break
a:for(int i = 0 ; i < 2; i++){
for(int j = 0; j < 5 ;j++){
System.out.print(“j=”+j);
break a;
}
System.out.println(“i=”+i);
}
给循环命名, 可在任意子循环中跳出或者结束指定循环
Random
/*
java中已经有的引用类型 Random类,作用,产生随机数
步骤:
1. 导入包, Random类,也在java.util文件夹
2. 公式: 创建出Random类型的变量
3. 变量. 调用Random类中的功能,产生随机数
Random类,提供功能 , 名字 nextInt() 产生一个随机数, 结果是int类型
出现随机数的范围, 在功能nextInt(写一个整数), 整数: 随机出来的范围
随机数的范围在 0 - 指定的整数之间的随机数 nextInt(100) 0-99
产生浮点的随机数: 功能名字 nextDouble() 随机数的范围 0.0-1.0
随机数: 伪随机数, 虚拟机根据人写好的一个算法,生成出来的
*/
import java.util.Random;
public class RandomDemo{
public static void main(String[] args){
// 2. 公式: 创建出Random类型的变量
Random ran = new Random();
// 3. 变量. 调用Random类中的功能,产生随机数
// Random类中的,产生随机数的功能
int i = ran.nextInt(100);
System.out.println(i);
//问题? 产生随机数,范围 1-100之间
// nextInt(100) 0-99 + 1
double d = ran.nextDouble();
System.out.println(d);
}
}
Scanner
/*
引用数据类型, 介绍一个类 Scanner
java已经存在了,是Sun公司为我们做好的类,使用他
定义引用数据类型变量,和基本类型变量区别
int a = 1;
格式:
类型 变量名 = new 类型();
举例: 创建出Scanner类的变量
Scanner sc = new Scanner();
int a = 1;
每个引用类型,都有自己的功能,如何使用功能
公式:
变量.功能名字()
Scanner类,作用,让我在命令行中,接受键盘的输入
使用Scanner类步骤:
1. 导入包,指明类所在的文件夹, 关键字 import
java文件夹-util文件夹
2. 公式,创建出Scanner类型变量
3. 变量.使用Scanner类中的功能,完成键盘输入
*/
import java.util.Scanner;
public class ScannerDemo{
public static void main(String[] args){
// 类型 变量名 = new 类型();
// 创建出Scanner,类变量
Scanner sc = new Scanner(System.in);
//变量.功能名字() 接受键盘输入
// 功能: nextInt() 接受键盘输入,保证输入的是整数
// 功能接受的数据就是整数,功能运行后的结果就是整数类型
int i = sc.nextInt();
System.out.println(i);
//Scanner类的另一个功能 next() 接受键盘输入的字符串
String s = sc.next();
System.out.println(s);
}
}
数组、switch
/*
定义数组容器
定义数组容器,要素,强制数据类型的语言
必须有数据类型, 大小, 就是存储数据的个数
定义数组公式:
数据类型[] 变量名 = new 数据类型[存储元素的个数];
数据类型: 数组中存储元素的数据类型
[] 表示数组的意思
变量名 自定义标识符
new 创建容器关键字
数据类型: 数组中存储元素的数据类型
[] 表示数组的意思
元素个数,就是数组中,可以存储多少个数据 (恒定, 定长)
数组是一个容器: 存储到数组中的每个元素,都有自己的自动编号
自动编号,最小值是0, 最大值,长度-1
自动编号专业名次, 索引(index), 下标, 角标
访问数组存储的元素,必须依赖于索引, 公式 数组名[索引]
Java提供一个属性,操作索引的
数组的一个属性,就是数组的长度, 属性的名字 length
使用属性: 数组名.length 数据类型 int
数组的最小索引是0, 最大索引数组.length-1
数组的两个定义方式
数据类型[] 变量名 = new 数据类型[]{元素1,元素2,元素3};
注意事项: new 后面的中括号中,不允许写任何内容,写了就编译失败
数据类型[] 变量名 = {元素1,元素2,元素3};
*/
public class ArrayDemo{
public static void main(String[] args){
//定义数组,存储整数,容器长度, 3个
// 数据类型[] 变量名 = new 数据类型[存储元素的个数];
int[] arr = new int[3];
System.out.println(arr);
//通过索引的方式,数组中的三个元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr.length);
}
}
二维数组
/*
二维数组
数组中的数组,数组里面存储的还是数组
定义方式和一维数组很相似
int[][] arr = new int[3][4];
定义一个二维数组
[3] 表示: 二维数组中,有三个一维数组
[4] 表示: 三个一维数组中,每个数组的长度是4
最简单的二维数组定义方式
int[][] arr = { {1,4} ,{3,6,8}, {0,9,8} };
*/
public class ArrayArrayDemo{
public static void main(String[] args){
int[][] arr = new int[3][4];
System.out.println(arr);
System.out.println(arr[1]);
System.out.println(arr[2][3]);
}
}
switch
选择语句 switch语句
编写格式
swtich(表达式){
case 常量1 :
要执行的语句;
break;
case 常量2 :
要执行的语句;
break;
case 常量3 :
要执行的语句;
break;
default:
要执行的语句;
break;
}
执行流程: 表达式,和case后面的常量进行比较
和哪个case后的常量相同,就执行哪个case后面的程序,遇到break,就全结束
关键字: switch case default break
switch语句中的表达式的数据类型,是有要求的
JDK1.0 - 1.4 数据类型接受 byte short int char
JDK1.5 数据类型接受 byte short int char enum(枚举)
JDK1.7 数据类型接受 byte short int char enum(枚举), String
方法、重载
/*
方法的定义格式
修饰符 返回值类型 方法的名字 (参数列表...){
方法的功能主体
循环,判断,变量,比较,运算
return ;
}
修饰符: 固定写法 public static
返回值类型: 方法在运算后,结果的数据类型
方法名: 自定义名字,满足标识符规范, 方法名字首字母小写,后面每个单词首字母大写
参数列表: 方法的运算过程中,是否有未知的数据, 如果有未知的数据,定义在参数列表上 (定义变量)
return: 方法的返回, 将计算的结果返回. 结束方法
*/
public class MethodDemo{
public static void main(String[] args){
//调用方法, 方法执行起来
// 在方法main中,调用方法 getArea
int area = getArea(5,6);
System.out.println("面积是: "+area);
}
/*
要求: 计算一个长方形的面积
定义方法解决这个要求
分析方法定义过程:
1. 明确方法计算后的结果的数据类型 int 定义格式对应的就是返回值类型
2. 方法计算过程中,有没有未知的数据, 宽和长, 未知数据的数据类型 int
未知数的变量,定义在方法的小括号内
*/
public static int getArea(int w, int h){
//实现方法的功能主体
//int area = w * h;
return w * h;
}
}
方法,调用中的参数传递问题
1. 方法参数是基本数据类型
- 方法参数是引用类型
传递的是内存地址!
方法的重载特性 (overload)
在同一个类中,允许出现同名的方法,只要方法的参数列表不同即可,这样方法就是重载
参数列表不同: 参数的个数,数据类型,顺序
方法重载的注意事项
- 参数列表必须不同
- 重载和参数变量名无关
- 重载和返回值类型无关
- 重载和修饰符无关
技巧: 重载看方法名和参数列表
实现引用类型、ArrayList
实现引用类型
/*
测试,刚定义好的Phone类
创建引用类型变量的格式
数据类型 变量名 = new 数据类型();
实现引用类型的步骤
1: 导入包 , 类如果都是在同一个文件夹,不需要导入包
2: 创建引用类型的变量
3: 变量.类型中的功能
文件结构:
pack
Phone.java
test.java
*/
package pack;
public class test{
public static void main(String[] args){
// 2: 创建引用类型的变量
Phone p = new Phone();
//System.out.println(p); //输出内存的地址
//3: 变量.类型中的功能
//变量 p.的方式,调用类中的属性
//属性就是变量 , 赋值和获取值
p.color = "土豪金";
p.brand = "爱立信";
p.size = 5.0;
//获取属性值
System.out.println(p.color+" "+p.brand+" "+p.size);
}
}
ArrayList
/*
ArrayList集合的使用
也是引用数据类型
步骤:
1. 导入包 java.util包中
2. 创建引用类型的变量
数据类型< 集合存储的数据类型> 变量名 = new 数据类型 <集合存储的数据类型> ();
集合存储的数据类型: 要将数据存储到集合的容器中
创建集合引用变量的时候,必须要指定好,存储的类型是什么
ArrayList<String> array = new ArrayList<String>();
3. 变量名.方法
注意: 集合存储的数据,8个基本类型对应8个引用类型
存储引用类型,不存储基本类型
*/
import java.util.ArrayList;
public class ArrayListDemo{
public static void main(String[] args){
//创建集合容器,指定存储的数据类型
//存储字符串
ArrayList<String> array = new ArrayList<String>();
//创建集合容器,存储整数
ArrayList<Integer> array2 = new ArrayList<Integer>();
//创建集合容器,存储手机类型
ArrayList<Phone> array3 = new ArrayList<Phone>();
}
}
ArrayList 集合中的方法
add(参数) 向集合中添加元素,数据存储进去
方法中的参数类型,定义集合对象时候的类型是一致
ArrayListarray = new ArrayList ();
array.add(3);
get(int index) 取出集合中的元素,get方法的参数,写入索引
size() 返回集合的长度, 集合存储元素的个数
add(int 索引,存储的元素) 将元素添加到指定的索引上
set(int 索引,修改后的元素) 将指定索引的元素,进行修改
remove(int 索引) 删除指定索引上的元素
clear() 清空集合中的所有元素
对象
package cn.itcast.demo01;
/*
* 类的方式,描述现实中的事物 小汽车
*
* 小汽车 属性和功能
* 属性: 颜色 轮胎个数 变量定义
* 功能: 跑 方法
*
* 属性和方法,都属于类的成员
*
* 属性, 成员变量
* 方法, 成员方法
*/
public class Car {
//定义Car类的属性
//定义颜色属性
String color ;
//定义轮胎个数
int count ;
//定义跑的功能
public void run(){
System.out.println("小汽车在跑 ..."+color+"..."+count);
}
}
package cn.itcast.demo01;
/*
* 测试,自定义的类Car
* 创建出Car类的变量
* 变量,调用属性,成员变量
* 变量,调用方法
*/
public class CarTest {
public static void main(String[] args) {
//创建出Car类的变量 , 创建出Car类的对象,小汽车真的有了
Car c = new Car();
//对象.调用类中的属性和方法
c.color = "无色";
c.count = 5 ;
c.run();
}
}
成员变量和局部变量的区别
- 定义位置上的区别
成员变量,定义在类中,方法外
局部变量,方法内,语句内
- 作用域不同
成员变量,作用范围是整个类
局部变量,方法内,语句内- 默认值不同
成员变量,有自己的默认值
局部变量,没有默认值,不赋值不能使用- 内存位置不同
成员变量,跟随对象进入堆内存存储
局部变量,跟随自己的方法,进入栈内存- 生命周期不同
成员变量,跟随对象,在堆中存储,内存等待JVM清理 , 生命相对较长
局部变量,跟随方法,方法出栈生命相对较短
提高安全问题: 让外面的类,不允许直接调用我的成员变量
新的关键字 private 私有 属于成员修饰符,不能修饰局部变量
被private修饰的成员,只能在自己的本类中被使用
对私有变量,提供公共的访问方式: 方法
private int age ;
this关键字:
- 区分成员变量和局部变量同名情况
- 方法中,方位成员变量,写this.
继承
extends
关键字 extends
子类是Develop, 父类是Employee
子类自动拥有父类中可以继承的属性和方法
public class Develop extends Employee{
//在子类中,可以定义方法
public void print(){
System.out.println(name);
}
}
子类中,可以直接调用父类的成员
super
在子类中,调用父类的成员,关键字 super.调用父类的成员
子类 (派生类) 继承父类 (超类,基类)
this.调用自己本类成员
super.调用的自己的父类成员
public void showNum(){
//父类的中的方法showNum已经可以号码,子类直接用
super.showNum();
System.out.println(“显示姓名”);
}
Override
继承后,子类父类中成员方法的特点
子类的对象,调用方法的时候
子类自己有,使用子类
子类自己没有,调用的是父类
重载: 方法名一样,参数列表不同,同一个类的事情
方法的重写 Override
子类中,出现了和父类一模一样的方法的时候, 子类重写父类的方法, 覆盖
子类重写父类的方法,
保证子类方法的权限大于或者等于父类方法权限
四大权限 public > protected default private
抽象类
Develop.java
package cn.itcast.demo06;
/*
* 定义类开发工程师类
* EE开发工程师 : 工作
* Android开发工程师 : 工作
*
* 根据共性进行抽取,然后形成一个父类Develop
* 定义方法,工作: 怎么工作,具体干什么呀
*
* 抽象类,不能实例化对象, 不能new的
* 不能创建对象的原因: 如果真的让你new了, 对象.调用抽象方法,抽象方法没有主体,根本就不能运行
* 子类的方法必须覆盖父类的抽象方法
* 抽象类使用: 定义类继承抽象类,将抽象方法进行重写,创建子类的对象
*/
public abstract class Develop {
//定义方法工作方法,但是怎么工作,说不清楚了,讲不明白
//就不说, 方法没有主体的方法,必须使用关键字abstract修饰
//抽象的方法,必须存在于抽象的类中,类也必须用abstract修饰
public abstract void work();
}
JavaEE.java
package cn.itcast.demo06;
/*
* 定义类,JavaEE的开发人员
* 继承抽象类Develop,重写抽象的方法
*/
public class JavaEE extends Develop{
//重写父类的抽象方法
//去掉abstract修饰符,加上方法主体
public void work(){
System.out.println("JavaEE工程师在开发B/S 软件");
}
}
Test.java
/*
* 测试抽象类
* 创建他的子类的对象,使用子类的对象调用方法
*/
public class Test {
public static void main(String[] args) {
JavaEE ee = new JavaEE();
ee.work();
}
}
/*
* 抽象类,可以没有抽象方法,可以定义带有方法体的方法
* 让子类继承后,可以直接使用
*/
public abstract class Animal {
public void sleep(){
System.out.println("动物睡觉");
}
// private abstract void show();
//抽象方法,需要子类重写, 如果父类方法是私有的,子类继承不了,也就没有了重写
}
接口
MyInterface.java
/*
* 定义接口
* 使用关键字interface 接口名字
* 接口定义:
* 成员方法,全抽象
* 不能定义带有方法体的方法
*
* 定义抽象方法: 固定格式
*
* public abstract 返回值类型 方法名字(参数列表);
* 修饰符 public 写,或者不写,都是public
*
* 接口中成员变量的定义
* 成员变量的定义,具体要求
*
* 要求 : 必须定义为常量
* 固定格式:
* public static final 数据类型 变量名 = 值
*/
public interface MyInterface {
//public static final int a = 1;
//在接口中,定义抽象的方法
public abstract void function();
}
MyInterfaceImpl.java
/*
* 定义类, 实现接口,重写接口中的抽象方法
* 创建实现类的对象
*
* 类实现接口, 可以理解为继承
*
* 关键字 implements
* class 类 implements 接口{
* 重写接口中的抽象方法
* }
* 类实现接口
* class MyInterfaceImpl implements MyInterface
*/
public class MyInterfaceImpl implements MyInterface{
public void function(){
System.out.println("实现类,重写接口抽象方法");
}
}
Test.java
public class Test {
public static void main(String[] args) {
//创建接口的实现类的对象
MyInterfaceImpl my = new MyInterfaceImpl();
my.function();
}
}
接口中成员的特点
- 成员变量的特点, 没有变量,都是常量
固定定义格式: public static final 数据类型 变量名 = 值
public 权限
static 可以被类名直接.调用
final 最终,固定住变量的值
注意: public static final 修饰符,在接口的定义中,可以省略不写
但是,不写不等于没有
三个修饰符,还可以选择性书写
- 接口中的成员方法特点:
public abstract 返回值类型 方法名(参数列表)
修饰符 public abstract 可以不写,选择性书写
但是,写不写,都有- 实现类,实现接口,重写接口全部抽象方法,创建实现类对象
实现类,重写了一部分抽象方法,实现类,还是一个抽象类
重写接口中的抽象方法, public权限是必须的
可实现多个接口
/*
* 类C,同时去实现2个接口,接口A,B
* 作为实现类,C,全部重写两个接口的所有抽象方法,才能建立C类的对象
*
* C类,在继承一个类的同时,可以实现多个接口
* public interface A {
* public abstract void a();
* }
* public interface B {
* public abstract void b();
* }
* public abstract class D {
* public abstract void d();
* }
*/
public class C extends D implements A,B{
public void a(){
}
public void b(){
}
public void d(){
}
}
接口多继承
package cn.itcast.demo04;
/*
* 实现接口C,重写C接口的全部抽象方法
* 而且接口C,继承A,B
* D实现类,重写A,B,C三接口全部抽象方法
*
* 问: Java中有多继承吗
* 类没有多继承
* 接口之间多继承
* public interface A {
* public abstract void a();
* }
* public interface B {
* public abstract void b();
* }
* public interface C extends A,B{
* public abstract void c();
* }
*/
public class D implements C{
public void a(){}
public void b(){}
public void c(){}
}
多态
// 多态调用方法,方法必须运行子类的重写!!
//Java中,对象的多态性,调用程序中的方法
// 公式: 父类类型或者是接口类型 变量 = new 子类的对象();
Fu f = new Zi();
f.show();
//抽象类Animal,子类是Cat
Animal a = new Cat();
a.eat();
//接口Smoking,实现类Student
Smoking sk = new Student();
sk.smoking();
多态中,成员特点
成员变量:
编译的时候, 参考父类中有没有这个变量,如果有,编译成功,没有编译失败
运行的时候, 运行的是父类中的变量值
编译运行全看父类
成员方法:
编译的时候, 参考父类中有没有这个方法,如果有,编译成功,没有编译失败
运行的时候, 运行的是子类的重写方法
编译看父类,运行看子类
关键字instanceof
运算符比较运算符, 结果真假值
关键字, instanceof, 比较引用数据类型
Person p = new Student();
p = new Teacher()
关键字 instanceof 比较, 一个引用类型的变量,是不是这个类型的对象
p变量,是Student类型对象,还是Teacher类型对象
引用变量 instanceof 类名
p instanceof Student 比较,p是不是Student类型的对象,如果是,intanceof返回true
//两个子类,使用两次多态调用
Animal a1 = new Cat();
Animal a2 = new Dog();
//a1,a2调用子类父类共有方法,运行走子类的重写
a1.eat();
a2.eat();
//类型向下转型,强制转换,调用子类的特有
//防止发生异常: a1属于Cat对象,转成Cat类, a2属于Dog对象,转成Dog
//instanceof判断
if(a1 instanceof Cat){
Cat c = (Cat)a1;
c.catchMouse();
}
if(a2 instanceof Dog){
Dog d = (Dog)a2;
d.lookHome();
}
构造函数
Person.java
/*
* 自定义的Person类.成员变量,name age
* 要求在 new Person的同时,就指定好name,age的值
* 实现功能,利用方法去实现, 构造方法,构造器 Constructor
* 作用: 在new 的同时对成员变量赋值, 给对象的属性初始化赋值 new Person 对属性 name,age赋值
*
* 构造方法的定义格式
* 权限 方法名(参数列表){
* }
* 方法的名字,必须和类的名字完全一致
* 构造方法不允许写返回值类型 , void 也不能写
*
* 构造方法在什么时候,运行呢, 在new 的时候,自动执行
* 只运行一次,仅此而已
*
* 每个class必须拥有构造方法,构造方法不写也有
* 编译的时候,javac, 会自动检查类中是否有构造方法
* 如果有,就这样的
* 如果没有,编译器就会自动添加一个构造方法
* 编译器自动添加的构造方法: public Person(){}
* 自己手写了构造方法,编译的时候,不会自动添加构造方法!
*/
public class Person {
private String name;
private int age;
//定义出Person类的构造方法
public Person(String name,int age){
this.name = name;
this.age = age;
//System.out.println("我是一个空参数构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Test.java
package cn.itcast.demo01;
/*
* new 对象的时候,就是在调用对象的构造方法
* new Person(); 调用的是类中的空参数构造方法
* new Person("张三",20); 调用类中的有参数构造方法
*/
public class Test {
public static void main(String[] args) {
Person p = new Person("张三",20);
//对象p 调用方法getName,getAge
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
this可以在构造方法之间进行调用
this.的方式,区分局部变量和成员变量同名情况
this在构造方法之间的调用,语法 this()public Person(){ //调用了有参数的构造方法 //参数李四,20传递给了变量name,age this("李四",20); }
构造方法,传递String,int
在创建对象的同时为成员变量赋值public Person(String name,int age){ this.name = name; this.age = age; }
子类中,super()的方式,调用父类的构造方法
super()调用的是父类的空参数构造
super(参数) 调用的是父类的有参数构造方法
子类的构造方法, 有一个默认添加的构造方法
注意: 子类构造方法的第一行,有一个隐式代码 super()public Student(){ super(); }
子类的构造方法第一行super语句,调用父类的构造方法
public class Student extends Person{ public Student(){ super(); } }
构造方法第一行,写this()还是super()
不能同时存在,任选其一,保证子类的所有构造方法调用到父类的构造方法即可
小结论: 无论如何,子类的所有构造方法,直接,间接必须调用到父类构造方法
子类的构造方法,什么都不写,默认的构造方法第一行 super();public class Student extends Person{ public Student(){ //调用的是自己的构造方法 //间接形式调用到了父类的构造方法 this("abc"); } }
final、static
最终类
/*
* 在类的定义上,加上修饰符,final
* 类: 最终类, 不能有子类,不可以被继承
* 但是使用方式,没有变化,创建对象,调用方法
*
*/
public final class Fu {
public void show(){
System.out.println("最终类的方法");
}
}
final方法
/*
* 定义父类
* 一部分方法,写成final修饰
* 子类可以继承的,但是不能做重写
*/
public class Fu {
public final void show(){
System.out.println("fu类的最终方法");
}
public void function(){
System.out.println("fu类的一般方法");
}
}
static
Person.java
/*
* 定义Person类,
* 定义对象的特有数据,和对象的共享数据
* 对象的特有数据(非静态修饰) 调用者只能是 new 对象
* 对象的共享数据(静态修饰) 调用者可以是new 对象,可以是类名
*
* 被静态修饰的成员,可以被类名字直接调用
*/
public class Person {
String name;
public static void fun(){
System.out.println("hh");
}
static String className;
}
Test.java
public class Test {
public static void main(String[] args) {
System.out.println(Person.className);
//对象调用类的静态成员变量
p1.className = "基础班";
System.out.println(p2.className);
Person.fun();//调用静态方法
}
}
静态的注意事项
在静态中不能调用非静态为什么呢? 为什么静态不能调用非静态
生命周期静态优先于非静态存在于内存中
静态 前人 先人 非静态 后人
静态不能写this,不能写super
问题: static 修饰到底什么时候使用,应用场景
static 修饰成员变量,成员方法
成员变量加static, 根据具体事物,具体分析问题
定义事物的时候,多个事物之间是否有共性的数据!!
请你将共性的数据定义为静态的成员变量
成员方法加static, 跟着变量走
如果方法,没有调用过非静态成员,将方法定义为静态
多态静态
Fu.java
public class Fu {
static int i = 1;
public static void show(){
System.out.println("父类静态方法show");
}
}
Zi.java
public class Zi extends Fu{
static int i = 2;
public static void show(){
System.out.println("子类的静态方法show");
}
}
Test.java
/*
* 多态调用中,编译看谁,运行看谁
* 编译都看 = 左边的父类, 父类有编译成功,父类没有编译失败
* 运行,静态方法, 运行父类中的静态方法
* 运行,非静态方法,运行子类的重写方法
* 成员变量,编译运行全是父类
*
*
*/
public class Test {
public static final double PI = 3.14159265358979323846;
public static void main(String[] args) {
Fu f = new Zi();
// System.out.println(f.i);
//调用还是父类的静态方法,原因: 静态属于类,不属于对象
//对象的多态性,静态和对象无关,父类的引用.静态方法
f.show();
System.out.println();
}
}
匿名对象
Person
public class Person {
public void eat(){
System.out.println("人在吃饭");
}
}
Test.java
/*
* 有名字对象,引用类型变量,可以反复使用
* 匿名对象,没有引用变量,只能使用一次
*
* 匿名对象可以当作参数传递
* 匿名对象可以当作方法的返回值
*/
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.eat();
new Person().eat();
new Person().eat();
method(new Person());
Person p1 = method();
p1.eat();
}
//方法返回值是Person类型
//方法return语句,返回的是这个类的对象
public static Person method(){
//Person p = new Person();
return new Person();
}
//调用方法method,传递Person类型对象
public static void method(Person p){
p.eat();
}
}
内部类
Outer.java
/*
* 内部类的定义
* 将内部类,定义在了外部的成员位置
* 类名Outer,内部类名Inner
*
* 成员内部类,可以使用成员修饰符,public static ....
* 也是个类,可以继承,可以实现接口
*
* 调用规则: 内部类,可以使用外部类成员,包括私有
* 外部类要使用内部类的成员,必须建立内部类对象
*/
public class Outer {
private int a = 1;
//外部类成员位置,定义内部类
class Inner{
public void inner(){
System.out.println("内部类方法inner "+a);
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
/*
* 调用外部类中的内部类的方法inner()
* 依靠外部类对象,找到内部类,通过内部类对象,调用内部类的方法
* 格式:
* 外部类名.内部类名 变量 = new 外部类对象().new 内部类对象();
* 变量.内部类方法()
*/
Outer.Inner in = new Outer().new Inner();
in.inner();
}
}
文档、jar包
集合框架
异常
Throwable
Exception 异常 感冒,阑尾炎
将异常处理掉,可以继续执行
RuntimeException
Error 非典,艾滋,癌
必须修改程序
throw
/*
* 异常中的关键字
* throw,在方法内部,抛出异常的对象
* throw 后面,必须写new 对象,必须是异常的对象,必须是Exception或者子类
*
* 方法中声明异常关键字
* throws 用于在方法的声明上,标明次方法,可能出现异常
* 请调用者处理
* throws 后面必须写异常类的类名
*
* 调用了一个抛出异常的方法,调用者就必须处理
* 不处理,编译失败
*/
public class ExceptionDemo {
public static void main(String[] args) throws Exception {
int[] arr = {};
int i = getArray(arr);
System.out.println(i);
}
//对数组的最后索引*2,返回
public static int getArray(int[] arr) throws Exception {
//对方法参数进行合法性的判断,进行判断是不是null
if( arr == null){
//抛出异常的形式,告诉调用者
//关键字 throw
throw new Exception("传递数组不存在");
}
//对数组进行判断,判断数组中,是不是有元素
if(arr.length == 0){
//抛出异常的形式,告诉调用者,数组没有元素
throw new Exception("数组中没任何元素");
}
int i = arr[arr.length-1];
return i*2;
}
}
try…catch
/*
* 异常的处理方式:
* try...catch...finally
* 格式:
* try{
* 被检测的代码
* 可能出现异常的代码
* }catch(异常类名 变量){
* 异常的处理方式
* 循环,判断,调用方法,变量
* }finally{
* 必须要执行代码
* }
*/
public class ExceptionDemo1 {
public static void main(String[] args) {
int[] arr = null;
try{
int i = getArray(arr);
System.out.println(i);
}catch(NullPointerException ex){
System.out.println("###"+ex);
}catch(ArrayIndexOutOfBoundsException ex){
System.out.println("!!!!!!"+ex);
}
finally {
System.out.println("必须执行");
}//释放资源
System.out.println("Game Over");
}
/*
* 定义方法,抛出异常
* 调用者使用try catch
*/
public static int getArray(int[] arr)throws NullPointerException,ArrayIndexOutOfBoundsException{
//对数组判空
if( arr == null){
//手动抛出异常,抛出空指针异常
throw new NullPointerException("数组不存在");
}
//对数组的索引进行判断
if( arr.length < 3){
//手动抛出异常,抛出数组的索引越界异常
throw new ArrayIndexOutOfBoundsException("数组没有3索引");
}
return arr[3]+1;
}
}
/*
* 多catch写在一起
* 细节:
* catch小括号中,写的是异常类的类名
* 有没有顺序的概念,有
*
* 平级异常: 抛出的异常类之间,没有继承关系,没有顺序
* NullPointerException extends RuntimeException
* NoSuchElementException extends RuntimeException
* ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException extends RuntimeException
*
* 上下级关系的异常
* NullPointerException extends RuntimeException extends Exception
* 越高级的父类,写在下面
*/
最好用try…catch,少用throws
RuntimeException
/*
* 异常分为编译异常和运行时期异常
* 编译异常: 调用了抛出异常的方法,不处理编译失败 (try throws)
* 运行异常: 抛出的异常是RuntimeException类,或者是他的子类
*
* 运行异常的特点:
* 方法内部抛出的异常是运行异常, new XXXException
* 方法的声明上,不需要throws语句,调用者,不需要处理
* 设计原因:
* 运行异常,不能发生,但是如果发生了,程序人员停止程序修改源代码
*
* 运行异常: 一旦发生,不要处理,请你修改源代码, 运行异常一旦发生,后面的代码没有执行的意义
*/
public class RuntimeExceptionDemo {
public static void main(String[] args) {
double d = getArea(1);
System.out.println(d);
}
/*
* 定义方法,计算圆形的面积
* 传递参数0,或者负数,计算的时候没有问题
* 但是,违反了真实情况
* 参数小于=0, 停止程序,不要在计算了
*/
public static double getArea(double r){
if(r <= 0)
throw new RuntimeException("圆形不存在");
return r*r*Math.PI;
}
public static void function(){
int[] arr = {1,2,3};
//对数组的5索引进行判断,如果5索引大于100,请将5索引上的数据/2,否则除以3
//索引根本就没有
if(arr[5] > 100){
arr[5] = arr[5]/2;
}else{
arr[5] = arr[5]/3;
}
}
}
Throwable类中的方法
/*
* 三个方法,都和异常的信息有关系
* String getMessage() 对异常信息的详细描述 异常了!
* String toString() 对异常信息的简短描述 java.lang.Exception: 异常了!
* void printStackTrace() 将异常信息追踪到标准的错误流 异常信息最全,JVM默认调用方法也是这个方法
*/
public class ExceptionDemo1 {
public static void main(String[] args) {
try{
function();
}catch(Exception ex){
//System.out.println(ex.toString());
ex.printStackTrace();
}
}
public static void function() throws Exception{
throw new Exception("异常了!");
}
}
自定义异常
/*
* 自定义异常
* 继承Exception,或者继承RuntimeException
* 构造方法中,super将异常信息,传递给父类
*/
public class FuShuException extends RuntimeException{
public FuShuException(String s){
super(s);
}
public FuShuException(){}
}
*****************************************************
public class ExceptionDemo {
public static void main(String[] args) {
int avg = getAvg(50,60,-70,80);
System.out.println(avg);
}
/*
* 传递成绩,计算成绩的平均数
* 成绩没有负数,需要抛出异常,停止运算
*/
public static int getAvg(int...source){
int sum = 0 ;
for(int s : source){
if( s < 0){
throw new FuShuException("成绩错误 "+s);
}
sum = sum + s;
}
return sum/source.length;
}
}
/*
* 继承后,在子类重写父类方法的时候,异常处理
* 结论:
* 父类的方法,如果抛出异常,子类重写后
* 可以不抛出异常
* 也可以抛出异常,但是,如果子类要抛,抛出的异常不能大于父类的异常
* 大于,都指的是继承关系
*
* 父类的方法,没有异常抛出,子类重写后
* 也不能抛出异常
* 如果子类中调用了抛出异常的方法,别无选择,只能try..catch处理
*/
IO、文件操作
多线程
Thread
/*
* 定义子类,继承Thread
* 重写方法run
*/
public class SubThread extends Thread{
public void run(){
for(int i = 0; i < 50;i++){
System.out.println("run..."+i);
}
}
}
****************************************
/*
* 创建和启动一个线程
* 创建Thread子类对象
* 子类对象调用方法start()
* 让线程程序执行,JVM调用线程中的run
*/
public class ThreadDemo {
public static void main(String[] args) {
SubThread st = new SubThread();
SubThread st1 = new SubThread();
st.start();
st1.start();
for(int i = 0; i < 50;i++){
System.out.println("main..."+i);
}
}
}
Runnable
/*
* 实现接口方式的线程
* 创建Thread类对象,构造方法中,传递Runnable接口实现类
* 调用Thread类方法start()
*/
public class ThreadDemo {
public static void main(String[] args) {
SubRunnable sr = new SubRunnable();
Thread t = new Thread(sr);
t.start();
for(int i = 0 ; i < 50; i++){
System.out.println("main..."+i);
}
}
}
*********************************************
/*
* 实现线程成功的另一个方式,接口实现
* 实现接口Runnable,重写run方法
*/
public class SubRunnable implements Runnable{
public void run(){
for(int i = 0 ; i < 50; i++){
System.out.println("run..."+i);
}
}
}
匿名内部类
/*
* 使用匿名内部类,实现多线程程序
* 前提: 继承或者接口实现
* new 父类或者接口(){
* 重写抽象方法
* }
*/
public class ThreadDemo {
public static void main(String[] args) {
//继承方式 XXX extends Thread{ public void run(){}}
new Thread(){
public void run(){
System.out.println("!!!");
}
}.start();
//实现接口方式 XXX implements Runnable{ public void run(){}}
Runnable r = new Runnable(){
public void run(){
System.out.println("###");
}
};
new Thread(r).start();
new Thread(new Runnable(){
public void run(){
System.out.println("@@@");
}
}).start();
}
}