基本知识
注释
java注释有三种:
- 单行注释://
- 多行注释:/* 注释内容 */
- 文档注释:/**
@Description:
@Author:
*/
标识符
类名:首字母大写+驼峰规则
方法名:首字母小写+驼峰规则
变量名:首字母小写+驼峰规则,所有的变量命名要见名知意,采用单词
常量:常量命名要用大写字母和下划线
注意:
类变量或者类的属性在类里面,在方法之外
方法中的变量是局部变量
static与类同时加载,类存在时,static就存在
局部变量在方法中,使用之前必须声明和初始化
八大基本数据类型
1、整数类型:
(1)byte:占一个字节(每个字节8比特),则byte的整数范围是-27到27-1,即-128到127.
(2)short:占两个字节,即16比特,整数范围:-215到215-1,即-32768到32767
(3)int:占4个字节,即32比特,整数范围:-231到231-1
(4)long:在数字后面加L或者l,例如:long num = 88L;占8个字节,即64比特,整数范围-263到263-1,long类型要在变量值后面加上L
2、小数类型
(1)float:单精度浮点型,占四个字节,32比特,有float单精度浮点型不是java的默认小数类型,所以要在变量值后面加上f或者F,其有效位数为8位,位数可以精确到7位有效数字,通常采用四舍五入法。
(2)double:双精度浮点型,占8个字节,是java的默认小数类型,有效位数16位
3、字符:一个字符占两个字节
char name = ‘A’ 声明一个字符变量,使用单引号,字符串使用双引号,字符只能是单引号,单引号中间是单个字符,可以声明一个字符,或者转移字符,或者直接使用unicode值来表示字符型常量
例如:
char c1 = ‘A’
char c2 = ‘\n’ \n表示换行符,这里说明System.out.println()输出之后换行,System.out.print()输出后不换行
char c3 = ‘\t’ \表示制表位,显示1-8个空格,当前面的内容不足8为时,补够8位,当前面的内容是8位时,加8个空格
字符换:String,通常使用双引号。’’ ''双引号中间可以使用多个字符
4、布尔值类型:
布尔值类型只有两种:true和false,
例如:boolean flag = true;
数据类型扩展
1、整数拓展:二进制0b, 八进制0,十进制,十六进制0x
类型转换
八大基本类型的优先级:
从低到到:byte(一个字节)-> short(两个字节)->int(四个字节)->long(八个字节)->float(四个字节)(浮点型的优先级高于整数类型的优先级)->double(八个字节)
1、自动类型转换:从低优先级到高优先级,进行自动类型转换
2、强制类型转换:从高优先级到低优先级进行强制类型转换
注意点:
类型转换不能对布尔值类型进行转换
不能将对象类型转换为不相干的类型
把容量高的类型转换为容量低的类型要进行强制类型转换
操作数比较大的时候注意溢出问题,对于多个零的数,数字之间可以采用下滑先进行分割。例如:10_0000_0000
快捷键的使用
Fn + end 快速跳到行尾
Fn + home 快速跳到行首
ctrl + D 复制上一行
ctrl + Y删除当前行
shift + 回车 跳到下一行,快速换行
基本运算符
算数运算符:+ - * / % ++ –
复制运算法:=
关系运算符:< > <= => == += !=
逻辑运算符:&& || !
位运算符:& | ^ >> <<
按位与:只有全1才为1
按位或:有1则为1,全零才为0
向左移位:等于乘以2
向右移位:等于除以2
用+进行字符串拼接
三元运算符:x ? y:z,表示x为真,则为y,否则为z
a++使用之后自加
++a 使用之前自加
a–,--a同理
scanner
scanner 创建一个扫描器对象,用于接收键盘数据
//scanner类中的next()以空格为结束符
//scanner类中的nextLine()以回车enter为结束符
import java.util.Scanner;
public class Day1 {
public static void main(String[] args) {
//创建一个扫描器对象,用于接收键盘数据
Scanner scanner = new Scanner(System.in);//通过scanner 创建一个对象,通多system.in 接收对象,System.in 表示输入,然后封装给一个对象scanner,类型是Scanner
System.out.println("使用next方式接收:");
//判断用户有没有输入字符
//使用scanner类的hasNext()或者hasNextLine判断是否还有输入的数据
if (scanner.hasNext()){
//使用next对象接收
//通过scanner类的next()或者nextLine()的方法获取输入的字符串
String str = scanner.next();
System.out.println("输出的内容为:"+str);
}
//凡是属于输入输出流的类IO流的类如果不关闭会一直占用资源,养成习惯用完就关掉凡是属于IO 流的类用完之后一定要关闭
scanner.close();
}
}
凡是属于IO流的类用完一定要关闭
import java.util.Scanner;
/*
scanner类的next()和nextLine()的区别:
next()以空格为结束符
nextLine()以回车enter为结束符
*/
public class nextLine {
public static void main(String[] args) {
//创建扫描器,从键盘接收数据
Scanner scanner = new Scanner(System.in);
//判断是否还有输入
if (scanner.hasNextLine()){
//等待用户输入
String str = scanner.nextLine();
System.out.println("输出为:"+str);
}
//凡是属于IO流的类用完只有一定要关闭
scanner.close();
}
}
IF 选择结构
import java.util.Scanner;
public class IfDemo1 {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
if(scanner.hasNextLine()){
int score = scanner.nextInt();
if (score<60){
System.out.println("不及格");
}else if (score >= 60&&score<80){
System.out.println("良好");
}else if (score >=80&&score<=100){
System.out.println("优秀");
}else {
System.out.println("成绩不合格");
}
}
scanner.close();
}
}
equals()用来判断两个字符串是否相等
import java.util.Scanner;
//equals()用来判断字符串是否相等
public class IfDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
//equals()用来判断字符串是否相同
if (s.equals("hello")){
System.out.println(s);
}else{
System.out.println("end");
}
scanner.close();
}
}
switch 匹配结构
switch匹配结构,判断变量与每个分支是否相等
public class SwitchDemo1 {
public static void main(String[] args) {
//switch case语句,匹配结构,判断变量与每个分支是否相等
//匹配一个具体的值,case穿透,如果没有break,则后面的case继续执行
char grade = 't';
switch (grade){
case 'a':
System.out.println("优秀");
break;//break 是可选语句,如果匹配成功,接结束,如果没有break,后面的分支还会执行,即break终止switch语句
case 'b':
System.out.println("良好");
break;
case 'c':
System.out.println("一般");
break;
case 'd':
System.out.println("不及格");
break;
default://默认,如果前面的匹配不成功,则输出这个
System.out.println("未知等级");
}
}
}
For 循环结构
public class ForDemo {
public static void main(String[] args) {
// for(初始化;布尔表达式;更新){代码语句}
//初始化;判断条件;迭代
for (int i=0;i<=100;i++){
System.out.println(i);
}
}
}
数组.for()用于遍历数组元素
public class ForDemo5 {
public static void main(String[] args) {
//遍历一个数字
int[] number = {10,20,30,40,50};//定义一个整形数组,int[]定义整形数组
for (int i=0; i<5; i++){
System.out.println(number[i]);
}
//遍历数组,主要用于遍历数组和集合对象
//for(声明语句:表达式){}
for (int x:number){
System.out.println(x);
}
}
}
continue 与 break的区别、do{}while() 和while(){}
break用于强制退出循环,不执行剩余的语句
continue用于终止某次循环,直接进入下一次循环的判断
do {}while ()用于先执行后判断,其循环至少执行一次
while(){}do用于先判断后执行
方法
.java文件是面向编程人员
.class文件是面向计算机
命令行javac是编译意思
方法说明:
(1)java是方法语句的集合,他们在一起执行一个功能
(2)方法包含于类或对象中,方法在程序中被创建,在其他地方被调用
(3)方法只能完成一个功能
(4)对象是类的实例化,类是构造对象的模板
例如:System.out.println() 调用System类中的标准输出对象out中的方法println()
main()方法是程序的主入口,一个项目中一般设置一个main()方法
public class MethodDemo1 {
//类的main方法,类的主方法,类程序的执行入口,public方法修饰符,void方法的返回类型,void为空,main为方法名,static是类变量
public static void main(String[] args) {
int sum = add(1,3);
System.out.println(sum);
}
//类中的其他方法在main方法之外
//public是修饰符,int是方法的返回值类型,方法名add(方法中的参数,一般是形参,在main方法中调用时候传入实参)
//该方法中如果没有static关键字,该方法不能直接调用,通过static关键字,使得成为类变量,才可以调用
public static int add(int a, int b) {
return a+b;
}
}
方法重载
/*
方法的定义:方法类似于其他语言中的函数,用来完成特定功能代码片段
方法结构:
修饰符 返回值类型 方法名(参数类型 参数名,参数类型 参数名){
方法体
return 返回值;
}
修饰符:可选,是为了告诉编译器如何调用该方法,定义了该方法的访问类型
返回值类型:方法可能会有返回值 returnValueType是方法返回值的数据类型,有些方法所执行的操作没有返回值,则returnValueType是关键字void,即返回值为空
方法名:命名是首字母小写加驼峰规则
参数类型:参数是一个占位符,当方法被调用时,传递值给参数,这个值被称为实参或者变量,参数是可选的,方法可以不包含任何参数
实参:调用方法时实际传输的参数
形参:定义方法时的参数
方法体:包含具体的语句
*/
/*
方法调用:对象名.方法名(实参列表)
如果方法返回一个值,方法调用通常当作一个值
如果方法返回值是void,方法调用是一条语句如System.out.println("ljid")
java都是值传递不是引用传递
*/
public class MethodDemo2 {
public static void main(String[] args) {
int max = max(12,23);
}
public static int max(int num1, int num2){
int result = 0;
if (num1==num2){
System.out.println("num1==num2");
return 0;
}
if (num1>num2){
result = num1;
}else{
result = num2;
}
return result;//return 除了返回结果之外,还可以终止方法
}
}
/*
方法重载:就是在一个类中,方法的名相同,形参不同
方法重载的原则:
方法名必须相同
方法的参数列表必须不同(个数不同,类型不同,参数排列顺序不同等等)
方法的返回类型可以相同也可以不同
方法名相同时,编译器会根据调用方法参数类型 等等逐个匹配
*/
可变参数
/*
可变参数:
在方法声明时,在指定参数类型后面加一个省略号(...)
一个方法中只能指定一个可变参数,他必须是方法的最后一个参数,任何普通的参数必须在他之前声明
public static void max(int... x){}
*/
public class MethodDemo3 {
public static void main(String[] args) {
MethodDemo3 MethodDemo3 = new MethodDemo3();
MethodDemo3.test(1,2,3,5,67,78);
}
public void test(double... i){
for(int j=0;j<i.length;j++){
System.out.println(i[j]);
}
}
}
/*
可变参数
一个方法中只能有一个可变参数,在指定参数类型后面加省略号(...)。同时该可变参数必须放在最后,即其他类型的参数必须放在可变参数之前声明
*/
数组
/*
数组:相同类型数据的有序集合,数组中的元素必须是相同类型,数组索引是从0开始的
对于普通变量;变量类型 变量名 = 变量值
对于数组:数组类型datatype,其中数组类型一般是datatype[],即类型后面加中括号,即datatype[] arrayrefvar;\例如int[]表示int类型的数组
java 使用new操作符来创建数组 daratype[] arrayrefvar = new daratype[arraysize]
利用array.length来获取数组的长度
*/
public class ArrayDemo1 {
public static void main(String[] args) {
int[] nums;//1、声明一个int类型的数组nums
nums = new int[10];//2、创建数组,给一个int类型的数组分配空间,数组大小为10,即该数组里面可以存放10个int类型的数字
//这里声明和创建一个数组可以写到一起
//int[] nums = new int[10];
//3、给数字元素赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
nums[5] = 6;
nums[6] = 7;
nums[7] = 8;
nums[8] = 9;
nums[9] = 10;
int sum=0;
for(int i=0; i<nums.length; i++){
sum += nums[i];
}
System.out.println("总和为:"+sum);
}
}
/*
数组的特点:
数组的长度是确定的,数组一旦被确定,其大小是不可以改变的
数组中的元素必须是相同类型,不允许出现混合类型
数组中的元素可以是任何类型的数据
数组本身就是对象
*/
/*
java内存:
1、堆:可以用来存放new的对象和数组
2、栈:可以存放基本变量类型
声明数组在堆中,创建数组在栈中
例如 int[] nums = new int[10];
其内存结构为:
*/
数组创建
public class ArrayDemo02 {
public static void main(String[] args) {
//数组静态初始化:数组创建加赋值
int[] a = {1,2,3,4,4,56,7,8};//所有的{}都表示一个数组
System.out.println(a[2]);
//动态初始化:声明+创建,
//动态初始化包含默认初始化,未进行赋值的,其中数据都是0,字符都是null
int[] b = new int[10];
b[0] = 10;
System.out.println(b[0]);
System.out.println(b[3]);//这里b[3]未进行赋值,但是其默认初始化为null
}
}
/*
数组的特点:
1、数组的长度是确定的,数组一旦创建,其大小不可以改变
2、数组中的所有元素必须是相同的类型,不允许出=出现混合类型
数组对象本身在堆中
java中对象是在堆中的
*/
/*
数组的边界:
数组的下标的合法区间:[0,length-1]
打印数组元素
package array;
public class ArrayDemo03 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};//定义一个数组
/*
//打印全部的数组元素
for(int i=0; i<arrays.length; i++){
System.out.println(arrays[i]);
}
//计算所有元素的和
int sum = 0;
for(int i=0; i<arrays.length; i++){
sum += arrays[i];
}
System.out.println(sum);
//查找最大元素
int result = 0;
for(int i=0; i<arrays.length; i++){
if (arrays[i]>result) {
result = arrays[i];
}
}
System.out.println(result);
/*
*/
//增强型的for循环,没有下标,用arrays.for回车生成,
//arrays表示数组,array表示数组中的变量
for (int array : arrays) {
System.out.println(array);
}
printArray(arrays);
int[] reverse = reverse(arrays);
for (int i : reverse) {
System.out.println(i);
}
}
//打印数组元素的方法,这里说明数组可以封装成方法的一个参数
public static void printArray(int[] arrays){
for(int i=0; i<arrays.length; i++){
System.out.println(arrays[i]);
}
}
//反转数组
public static int[] reverse(int[] arrays){
int[] result = new int[arrays.length];
for(int i=0,j=arrays.length-1; i<arrays.length; i++,j--){
result[j] = arrays[i];
}
return result;
}
}
二维数组
package array;
/*
多维数组:多维数组可以看成数组的数组。例如二维数组。其中每一个元素都是一个数组,多维数组可以理解为数组里面嵌入数组
二维数组的定义方法:
int[][] a = new int[2][5];
即二维数组a可以看成2行5列的数组
*/
public class ArrayDemo04 {
public static void main(String[] args){
//定义了一个二维数组,该二维数组是四行两列
int[][] array = {{1,2},{2,3},{3,4},{4,5}};
//获取数组的长度
System.out.println(array.length);
System.out.println(array[2].length);
//输出数组中的所有元素
for(int i=0; i<array.length; i++){
for(int j=0; j<array[i].length; j++){
System.out.println(array[i][j]);
}
}
//遍历数组可以用array.for+回车遍历数组遍历数组元素
//for(int array:arrays){}其中arrays表示要遍历的数组,array表示数组中的元素,可以自己定义,对于多维数组的遍历直接用嵌套就行
System.out.println("===============");
for (int[] ints : array) {
for (int anInt : ints) {
System.out.println(anInt);
}
}
}
}
数组中的方法:输出数组,数组排序,数组填充
package array;
//数组中的Arrays
/*
说明了Arrays类中的各种方法可以调用
Arrays.toString()将制定数组内容转化为字符串表示,用逗号隔开,两端加中括号
Arrays.sort()对数组进行排序,这里sort()是升序排列
Arrays.fill(array,fromindex,toindex,val)将数组array中的开始索引到结束索引的元素用0填充,注意左开右闭
*/
import java.util.Arrays;
public class ArrayDemo05 {
public static void main(String[] args) {
int[] a = {1,2,3,4,44,5555,455,5667,5555,5554};
int[] b = {1,2,3,4,44,555,455,567,5555,5554,758};
//打印数组的方法
//Arrays.toString()将指定的数组内容转化成字符串表示,每个字符用逗号,隔开,在外面加上中括号
System.out.println(Arrays.toString(a));
printArray(a);
//利用Arrays类中的sort方法对数组进行排序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//数组填充Arrays.fil(array,fromindex, toindex,val),将数组array的开始索引是2,结束索引是4,注意左闭右开,结束不包括,将这些元素用零填充
Arrays.fill(a,2,4,0);
System.out.println(Arrays.toString(a));
}
//打印数组可以自己定义方法
public static void printArray(int[] a){
for(int i = 0; i < a.length; i++){
if (i == 0){
System.out.print("[");
}if (i == a.length-1){
System.out.println(a[i] + "]");
}else{
System.out.print(a[i] + ", ");
}
}
}
}
冒泡排序
package array;
import java.util.Arrays;
/*
冒泡排序原理:从后依次往前比较,首先判断数组长度,确定外层比较多少次,每次比较出一个数
从后往前依次比较,较小的向前移动,知道比较出最小的
内层循环与已经比较出的个数有关,例如已经比较出了2个,则内层循环的比较个数就要减去2
依次循环,知道结束
注意:
内层循环比较时,如果是从后往前比较,则是先去定最小的,如果是从前往后比较,先去确定最大的
*/
public class ArrayDemo06 {
public static void main(String[] args) {
int[] array = {23,45,43,5,6,8,456,454};
int[] sort = sort(array);
System.out.println(Arrays.toString(sort));
int[] ints = sortDec(array);
System.out.println(Arrays.toString(ints));
}
/*
冒泡排序:比较数组中两个相邻元素的大小,如果第一个元素比第二个元素大,则交换他们的位置
每一次比较都会产生一个最大元素和一个最小元素
下一轮可以少一次排序
依次循环知道结束
*/
public static int[] sort(int[] array){
int temp = 0;
//确定外层循环,外层循环长度是数组长度
for (int i = 0; i < array.length - 1; i++) {
//内存循环次比较,,同时比较过的不在进行比较,所以每次比较的次数都在减少,例如前两个数已经比较完了,则剩下的比较次数要减去2
boolean flag = false;
for(int j = array.length-1; j>i; j--){
if (array[j] < array[j-1]){
temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
flag = true;
}
}
if (flag == false){
break;
}
}
return array;
}
public static int[] sortDec(int[] array){
int temp = 0;
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j<array.length-1-i; j++){
if (array[j+1]<array[j]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
}
稀释数组
package array;
import org.w3c.dom.ls.LSOutput;
import java.util.Arrays;
/*
稀疏数组:当一个数组的大部分元素为0或者一个数组中的大部分元素为同一个值时可以采用稀疏数组进行保存该数组
稀疏数组用来记录一个数组中有多少行,多少列,以及有多少个有效数值,0除外如下
行数 列数 有效值的个数
11(共有11行) 11(共有11列) 8(有效值的个数为8)
3(第三行) 4(第四列) 15(有效值为15)
一下依次记录原始数组中的有效值的位置,
稀疏数组总共有3列,行数为有效值的个数+1.因为第一行表示原始数组的总行数、总列数以及有效值的个数
如下的例子:记录五子棋,空白为0,1:黑棋,2:白旗,共有11行11列
*/
public class ArrayDemo07 {
public static void main(String[] args) {
//创建原始数组 11行11列 1:黑棋,2:白旗
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始数组
System.out.println("输出原始数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
//转换为稀疏数组保存
//首先要获取数组中有效值的个数,0除外
int sum = 0;
for (int i = 0; i <array1.length; i++){
for (int j = 0; j<array1[i].length; j++){
if (array1[i][j] != 0){
sum++;
}
}
}
//得到原始数组的有效值的个数之后开始建立稀疏数组
int[][] array2 = new int[sum +1][3];
array2[0][0] = array1.length;
array2[0][1] = array1[0].length;
array2[0][2] = sum;
int count = 0;
for (int i = 0; i < array1.length; i++){
for (int j = 0; j < array1[i].length; j++){
if (array1[i][j] != 0){
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
System.out.println("输出稀疏数组");
for (int[] ints : array2) {
for (int anInt : ints){
System.out.print(anInt + "\t");
}
System.out.println();
}
//还原原始数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for (int i = 1; i < array2.length; i++){
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
System.out.println("还原的原始数组");
for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
}
/*
稀疏数组作用
记录原始数组的大小(行数和列数)以及有效值的个数以及每个有效值的个数
稀疏数组为3列,行数为有效值的个数加上1,因为第一行用来记录行数列数和有效值个数
*/
面向对象
类、对象关系
package objectOrientedProgramming.Application;
//一个项目只存在一个main方法,是程序的主入口,main方法放在在总的测试类中
//不要每个类中都放main方法,在总的测试类中加一个main方法就可以了
public class Application {
public static void main(String[] args) {
//类是抽象的,需要实例化
//类实例化之后会返回一个自己的对象
//demo01对象就是Demo01类的一个具体实例对象
//同一个类可以产生不同的对象
// Demo01 xiaoming = new Demo01();
// Demo01 xiaohong = new Demo01();
// xiaoming.name = "xiaoming";
// System.out.println(xiaoming.name);
//使用new关键字实例化一个对象
Demo02 demo02 = new Demo02();
System.out.println(demo02.name);
Demo03 demo03 = new Demo03();
demo03.name = "haha";
demo03.age = 3;
demo03.shout();
System.out.println(demo03.name);
System.out.println(demo03.age);
}
}
package objectOrientedProgramming.Application;
public class Demo04 {
public static void main(String[] args) {
/*
总结:
1、类与对象:类是一个模板,类是抽象的,对象事是一个具体实例,对象事具体的
2、方法
3、对象的引用;
引用类型:除过八大基本类型,其他的都是引用类型。
对象事通过引用来操作的
4、类中只有两个:
静态的属性:属性
动态的行为:方法
*/
/*
java面向对象的三大特征:
封装、 继承、多态
*/
}
}
面向对象的本质:用类的方式组织代码,用对象的方式封装数据
package objectOrientedProgramming;
/*
属性+方法=类
面向过程:线性思维,先考虑第一步在考虑第二步做什么
面向对象:分类的思维模式
*/
/*
面向对象编程:object oriented programming
面向对象编程的本质:以类的方式组织代码,以对象的方式封装数据
*/
//Demo1类,一个类中有很多方法,,其中main方法是类的程序主入口
//方法中的修饰符public,是公共的意思,所有人都可以访问这个方法
public class Demo01 {
public static void main(String[] args) {
}
//方法:public修饰符公共的意思,所有人都可以访问这个方法
//String是方法的返回值类型,sayHello是方法名,首字母小写加驼峰原则,括号中包含参数类型和参数名
/*
修饰符 返回值类型 方法名(参数类型 参数,参数类型 参数){
方法体
return 返回值;
}
return表示方法结束
*/
public String sayHello(int a, double b){
return "null";
}
}
静态方法(static)和非静态方法
package objectOrientedProgramming;
//方法有两种:静态方法 加了static、 非静态方法,没有加static
public class Demo02 {
public static void main(String[] args) {
Student.say();//另一个类中的静态方法,可通过类名.方法名调用
//Student.sayDemo();//另一类中的非静态方法不能通过类名.方法名调用,需要通过类的实例化对象调用,因为非静态方法只有在对象创建后才存在
Student student = new Student();
student.sayDemo();//因此另一个类中的非静态方法只有通过类的实例化后,即创建对象之后才可以通过对象调用,不能直接通过类名调用
}
public void demo(){
//Student.sayDemo();//这里说明student类中的非静态方法(普通方法)在另一个类的任何方法中(包括静态和非静态方法)都不能通过类名.方法调用
//必须通过类的实例化。即创建对象后,通过对象调用
Student student = new Student();
student.sayDemo();//即必须通过对象调用
}
public static void a(){
b();//同一个类中,静态方法之间可以互相调用,因为static静态方法与类同时加载,类存在,static就存在
//c();//同一个类中,在静态方法中不能调用非静态方法,因为非静态方法在类的实例化后,即对象创建后才存在
}
public static void b(){
}
public void c(){
d();//同一个类中非静态方法之间可以互相调用
a();//同理,同一个类中,在非静态方法中可以调用静态方法,因=因为静态方法与类同时加载
}
public void d(){
}
}
package objectOrientedProgramming;
//学生类
public class Student {
/*
(1)如果一个方法中有static关键字,说明该方法是静态方法,因此该方法是和其所在的类是同在的,
可以在另一个类中中通过当前类名.方法调用,不需要通过类的实例化,不需要创建对象之后调用它
(2)如果一个类中有多个静态方法,其之间可互相调用,或者说一类中的多个非静态方法,即普通方法,其之间也可以互相调用
(3)但是如果一个类中既有静态方法,又有非静态方法,则静态方法和非静态方法之间不能互相调用
因为静态方法是和类一起加载的,与类同时存在,即类存在时static就存在,而非静态方法,即普通方法与对象有关,对象创建之后才存在,需要类的实例化
通过类的实例化对象调用非静态方法
*/
public static void say(){
System.out.println("hello");
}
public void sayDemo(){
System.out.println("hello world");
}
}
构造器
package objectOrientedProgramming.Application;
/*
构造器:用于创建对象时初始化对象属性的方法,也叫构造方法啊
*/
//这里是java文件,编译之后会生成一个class文件
public class Demo02 {
//一个类中即使什么都不写,他也会存在一个方法,该方法就是构造方法
/*
构造方法有两个特点:(1)构造方法名必须和类的名字相同(2)必须没有返回值类型,也不能写void
构造方法是默认生成的。这里显示的定义个构造方法
*/
String name;
public Demo02(){//无参构造器,构造方法名和类名相同,没有返回类型,也没有void
//构造方法的作用是实例化对象是初始化对象属性,即实例化初始值
this.name = "qingqiang";
/*
总结构造器的作用:
1、使用new关键字必须要有构造器:即使用new关键字其本质是在调用构造器。在调试过程中可以看到使用new关键字新建对象(进行类的实例化)时
首先进入类的构造器,对类的属性进行初始化,然后返回类的对象
2、构造器一般用来初始化值
*/
//有参构造器
}
//一旦定义了有参构造,无参构造就必须显示定义
public Demo02(String name){
this.name = name;//这里后面的name是形式参数
}
//我的键盘是:Fn + alt + insert 自动生成构造器、通常是alt + insert
/*
构造器:
构造器名必须和类名相同,而且没有返回值
作用:
使用new关键字本质是在调用构造器,即使用new关键字进行类的实例化时,首先进入类的
构造器,进行对象属性的初始化,然后返回对象
初始化对象属性
注意点:
定义了有参数构造,如果想使用无参构造,必须显示定义一个无参数构造
Fn + alt + insert创建构造器
this.name表示当前类的
*/
}
继承
package objectOrientedProgramming.Demo;
//A类是B类的子类
//A继承B
public class A extends B {
@Override//注解。有功能的注释,override本身表示重写的意思
public void test() {
System.out.println("A=>test");
}
}
package objectOrientedProgramming.Demo;
//B类是父类
//重写都是方法的重写,与属性无关
public class B {
public void test(){
System.out.println("B=>test");
}
}
package objectOrientedProgramming.Demo;
public class Application {
public static void main(String[] args) {
}
}
/* //String name = "hahha";
// Demo01 s1 = new Demo01();
// String name = s1.getName();
// s1.setName("qianqiang");
// System.out.println(s1.getName());
// s1.setAgel(6);
// System.out.println(s1.getAgel());
//Student student = new Student();
// student.say();
// student.test(name);
// student.test2();
//静态方法和非静态方法区别很大
//静态方法:static。方法的调用只和左边定义的数据类型有关,和右边的类型无关
// A a = new A();//A类的引用a指向子类A
// a.test();//调用的是A类的静态方法
//父类B的引用b指向了子类A类
// B b = new A();//子类重写了父类的方法,对于非静态方法,虽然A类指向了B,但是还是A类
// b.test();//调用的是B类的静态方法
}
//重写之和非静态方法有关,与静态方法无关*/
package objectOrientedProgramming.Demo;
//Person类是父类
//extends是扩展的意思,子类是父类的扩展
//继承是类和类之间的一种关系
//注意:在java中所有的类都默认直接或者间接继承object类
//java中只有单继承,没有多继承,即一个父类(基类)可以有多个子类(派生类),但是一个
//子类只能有一个父类
public class Person {
public Person() {
System.out.println("父类无参构造器");
}
public void say(){
System.out.println("nihao");
}
//ctrl + H 打开一个树
protected String name = "你好";
//父类私有的方法无法被子类继承
public void print(){
System.out.println("weinihao");
}
}
package objectOrientedProgramming.Demo;
//Student类是子类或者派生类
//子类继承父类,就会拥有父类的全部方法
public class Student extends Person {
public Student() {
//隐藏代码:默认调用父类的无参构造
super();//调用父类的构造器必须在子类的第一行,通常super()是隐藏的
System.out.println("子类无参构造器");
}
protected String name = "nihao";
public void test(String name){
System.out.println(name);//当前类的属性
System.out.println(this.name);
System.out.println(super.name);//父类的属性
}
public void print(){
System.out.println("student");
}
public void test2(){
print();//当前类的
this.print();//当前类的
super.print();//父类的方法
}
}
封装
package objectOrientedProgramming.Demo;
//类:私有private
public class Demo01 {
//属性私有,加上private关键字
private String name;//名字
private int id;//学号
private char sex;//性别
private String namew;
private int agel;
private char idd;
public String getNamew(){
return this.namew;
}
public void setNamew(String namew){
this.namew = "ljaj";
}
public void setAgel(int agel) {
this.agel = agel;
}
public int getAgel() {
return agel;
}
//提供一些可以操作这些属性的方法
//提供一些public的get、set方法
//get:获得这个数据或者属性
public String getName(){
return this.name;
}
//set:给这个属性或者数据设置值
public void setName(String name){
this.name = name;
}
public int getId() {
return id;
}
/*
封装:是对数据的隐藏,禁止直接访问对象中的一个数据,而应该通过接口来访问
封装的意义:
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、提供系统的可维护性
*/
}
/*
属性封装
将属性设置为私有属性,不能直接使用,通过get获取属性
通过set设置属性的值
*/
多态
package objectOrientedProgramming.demo02;
public class StudentPer extends PersonS {
@Override//一旦子类重写了父类的方法,就会执行子类,父类的方法就会被隐藏
public void run() {
System.out.println("nihao");
}
public void eat(){
System.out.println("eat");
}
}
/*
多态的注意事项:
1、多态是方法的多态,属性没有多态
2、父类和子类之间有联系,类型转换之间一定要有关联,如父类子类等等
3、多态存在的条件:(1)要有继承关系,(2)方法需要重写(否则调用的都是各自的方法)(3)父类的引用指向子类
1、static 静态方法,属于类,不属于对象,不能被重写
2、final: 常量,不能被重写
3、private 私有的方法,不能被重写
*/
注意
package objectOrientedProgramming;
import objectOrientedProgramming.demo02.PersonS;
import objectOrientedProgramming.demo02.StudentPer;
import objectOrientedProgramming.demo03.PersonA;
import objectOrientedProgramming.demo03.StudentA;
import objectOrientedProgramming.demo03.TeacherA;
public class ApplicationD {
public static void main(String[] args) {
//一个对象的实际类型是确定的,例如都是student类,但是一个对象指向的引用类型不确定,例如Person Object
// 但是一个对象可以指向的引用类型就不确定了
//父类的引用指向子类的类型,父类Person 父类的引用s2,或者说该对象的实际类型是student,但是
//该对象的指向的引用类型为Person,
//StudentPer能调用的方法都是自己的或者继承父类的
/*
StudentPer s1 = new StudentPer();
//PersonS 父类型,父类虽然可以指向子类,但是不能调用子类独有的方法
PersonS s2 = new StudentPer();
Object s3 = new StudentPer();
//对象能执行哪些方法,主要看对象左边的类型
s2.run();//一旦子类重写父类的方法,就会执行子类
s1.run();
s1.eat();
//s2.eat();当子类重写父类的方法,父类的方法就会被隐藏,从而执行子类的方法,当子类中的方法父类中没有时,父类无法调用该方法
*/
//object > String
//object > > personA > teacherA
//Object > personA > StudentA
//System.out.println(x instanceof y);能不能编译通过取决于这两者之间是否存在父子关系
/*
Object object = new StudentA();
System.out.println(object instanceof StudentA);//判断两个类之间是否存在父子关系
System.out.println(object instanceof PersonA);
System.out.println(object instanceof Object);
System.out.println(object instanceof TeacherA);
System.out.println(object instanceof String);
PersonA personA = new StudentA();
System.out.println(personA instanceof StudentA);//判断两个类之间是否存在父子关系
System.out.println(personA instanceof PersonA);
System.out.println(personA instanceof Object);
System.out.println(personA instanceof TeacherA);
//System.out.println(personA instanceof String);PersonA与String之间没有任何关系
*/
//类型之间的转换,父类 子类,高转低需要强制转换,
//高 低,将studentA()低类转换为PersonA类,不需要强制转换
PersonA studentA = new StudentA();
//studentA.go();//studentA对象属于PersonA类,是高类(父类),无法调用子类的方法,高类无法调用低类的方法,因此高类无法直接转化为低类,需要强制转换
//将studentA这个对象转换为Student类型,就可以使用Student类型的方法了
StudentA obj = (StudentA) studentA;//通过强制类型转换,将studentA对象转化为StudentA类,就可以调用StudentA类的对象
obj.go();
//可以简写
((StudentA)studentA).go();
StudentA studentA1 = new StudentA();
studentA1.go();
//低类型转为高类型,即子类转为父类可以回对视子类的某些方法。即可能回丢失自己本来的一些方法
PersonA person = studentA1;//父类的引用指向子类的对象
//person.go();
/*
1、父类的引用指向子类的对象
2、把子类转换为父类,向上转型,不需要强制转换,但是会丢失子类的某些方法
3、把父类转化为子类,向下转换,需要要强制转换
4、方便方法调用,减少重复的代码
*/
}
}
总结
super注意点:
1、super调用父类的构造方法,必须在构造方法的第一个。
2、super只能出现在子类的方法或者构造方法中
3、super和this不能同时调用构造方法
vs this:
代表的对象不同
this:表示本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件下使用
构造方法:
this():默认调用本类的构造方法:
super()调用父类的构造方法
重写:重写只针对方法,需要有继承关系。子类重写父类的方法
特定:
方法名必须相同
参数列表也必须相同
修饰符范围可以扩大,但是不能缩小, public > protected > default > private,就是说子类的修饰符必须必大于等于父类修饰符范围
重写可能会抛出异常,异常的范围可以被缩小,但是不能扩大
重写:子类的方法必须要和父类的方法要一致,方法体不同
为什么需要重写:
1、父类的功能子类不一定需要,或者不一定满足
alt+insert 选中override
对于静态方法:方法的调用只和创建对象左边定义的数据类型有关,与右边的类型无关
对于非静态方法,可能会出现子类重写父类的方法
instanceof
package objectOrientedProgramming.demo03;
//instanceof 引用类型转换,用来判断一个对象是什么类型,也可以用来判断两个类之间是否存在父子关系
public class PersonA {
public void run(){
System.out.println("run()");
}
}
代码块
package objectOrientedProgramming.demo04;
public class Person {
{
//代码块(匿名代码块),程序在执行的时候不能主动调用这个代码块
//匿名代码块在创建对象的时候自动创建,在构造器之前,属于第二个执行
System.out.println("匿名代码块");//可以用来赋初始值
}
public Person() {
System.out.println("构造方法");
}
static {
//静态代码块,与类同时存在,类加载时就存在,永久存在
System.out.println("静态代码块");//与类同时存在,类加载时便加载,属于第一个执行
}
public static void main(String[] args) {
Person person = new Person();
System.out.println("=====================");
Person person1 = new Person();//这一步的作用是说明static静态代码块与类同时加载,只加载一次,便永久存在,同一个类中值加载一次
}
}
抽象类
package objectOrientedProgramming.demo05;
//对于抽象类的所有方法,继承了他的子类,都必须要实现它的方法,类A 继承了类Action,则类A 必
// 须要实现父类的所有方法,除非子类也是abstract抽象类
public class A extends Action {
@Override
public void doSomeThing() {
}
}
package objectOrientedProgramming.demo05;
//在一个类中使用abstract,变为抽象类,
//java中类只有单继承,没有多继承,但是接口可以实现多继承
public abstract class Action {
//约束,有人帮实现
//抽象方法,只有方法名字,没有方法实现
public abstract void doSomeThing();
/*
抽象类的特点:
1、不能new这个抽象类来创建对象,只能靠子类取实现它,起到一个约束的作用
2、抽象类中可以写普通方法
3、抽象方法必须在抽象类中
抽象的抽象:约束
*/
}
接口
package objectOrientedProgramming.demo06;
/*
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范,接口就是规范,定义的是一组规则,接口的本质是契约,
声明接口的关键字是interface
*/
//接口都要有实现类
public interface UserService {
//接口中的所有定义都是抽象的,没有具体的实现方法,只有规范
//接口中的方法默认都是抽象的,public abstract
//public abstract void user();//有接口中的方法默认都是抽象的,所以前面的public abstract 可以省略不写
//定义四个方法,并没有具体实现
void add(String name);//可以省略public abstract,因此是默认的
void delete(String name);
void update(String name);
void query(String name);
}
package objectOrientedProgramming.demo06;
//一个类可以实现接口 Implements 实现接口
//实现了接口的类,就需要重写接口中的方法
//利用了接口实现了多继承,接口中只有方法的定义,没有实现
public class UserServiceImpl implements UserService, TimeService {
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
/*
接口的作用:
1、约束
2、定义一些方法,让不同的人实现
3、 方法都是抽象方法,public abstract
4、静态常量 public static final
5、接口不能被实例化,接口中没有构造方法
6、implements 可以实现多个接口,接口可以实现多个
7、 实现接口必须要重写接口中的方法
*/
内部类
package objectOrientedProgramming.demo07;
/*
内部类就是在一个类的内部在定义一个类,A类中定义一个B类,那么B类相对于A类来说就成为内部类,而A类相对于B类来说称为外部类
分为:
成员内部类
静态内部类
局部内部类
匿名内部类
*/
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是一个外部类的方法");
}
//当加入static时,成为静态内部类,与外部类同时加载,此时不能访问外部类的非静态属性
public static class inner {
public void in(){
System.out.println("这一个内部类的方法");
}
//可以获得外部类的私有属性,或者方法
public void getId(){
//System.out.println(id);
}
}
//局部内部类
public void method(){
class Iner {
public void in(){
}
}
}
}
//一个java文件中可以有多个class,但是只能有一个public class
class A {
}
package objectOrientedProgramming.demo07;
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.out();
//通过这个外部内来实例化这个内部类
//Outer.inner inner = outer.new inner();
// inner.in();
// inner.getId();
}
}