一.for循环与while循环的区别
1.格式
for循环:
for(初始化语句;条件表达式;步长语句){
循环体语句;
}
while循环:
初始化语句;
while(条件表达式){
循环体语句;
步长语句;
}
2.是否节省内存空间
for循环结束,这个变量及时从内存中释放掉了
while循环结束,这个变量依然可以访问的
3是否明确循环次数
for循环:明确循环次数
while循环:不明确循环次数
二.死循环及其应用
格式:
格式1:
for(;;){
循环体语句;
}
格式2:(推荐)
while(true){
循环体语句;
}
应用:
需求:使用Math类中的方法 random()获取一个1-100之间的随机数
//导包
import java.util.Scanner;
class GuessGame{
public static void main(String[] args){
//产生一到一百之间的随机数
int number = (int)(Math.random()*100+1);
//做while死循环
while(true){
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要猜的数字:");
int guess = sc.nextInt();
//做if判断,提示大小,猜对直接结束
if(guess>number){
System.out.println("你猜大了");
}else if(guess==number){
System.out.println("你猜对了");
break;
}else{
System.out.println("你猜小了");
}
}
}
}
三.方法
1.概念
使用{}将代码包裹起来,并给这个代码起一个名字:方法名---->以后直使用方法名调用.
2.分类
<1>有返回值类型的方法的定义
1.固定格式:
public static 返回值类型 方法名(形式参数类型1 参数名称1,...){
业务需求...
return 结果;
}
2.调用方法:赋值调用
需求:求和两个数据的和
两个明确:
1)明确返回值类型: int类型
2)明确参数类型以及参数个个数:int类型 两个参数求和
public static void main(String[] args){
//调用add()方法,输出结果
add(10,20);
System.out.println("二者之和为:"+add(10,20));
}
public static int add(int m,int n){
//返回需求结果
return m+n ;
}
/*注意事项:定义方法时,必须携带参数类型;
调用方法时,实参不用携带数据类型.*/
<2>无返回值类型的方法定义
语法要求:如果没有具体返回值结果,使用void来代替返回值类型
//1.定义格式:
public static void 方法名(形式参数类型1 变量名1,..){
直接输出语句或者
其他业务操作;
}
/*2.实例:
需求:键盘录入一个n数据,打印nn乘法表*/
import java.util.Scanner;
class Demo{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入乘法表阶数:");
int n = sc.nextInt();
printChengfabiao(n);
}
public static void printChengfabiao(int n) {
for(int x = 1 ; x <= n ;x ++){
for(int y = 1 ; y <= x ; y ++){
System.out.print(y+"*"+x+"="+y*x+"\t") ;
}
System.out.println() ;
}
}
}
注意:Java中不存在void类型(替代词)
3.重载
定义: 方法名相同,参数列表不同,与返回值无关.
参数列表不同:
1)数据类型一样的,参数个数不同
2)参数个数一样,类型不同
参数个数不一样,参数类型不同
//举例:求n个数之和,方法名均为sum;
class FunctionDemo{
public static void main(String[] args){
//使用实际参数
//输出调用
System.out.println(sum(10,20)) ;
System.out.println("------------------") ;
//System.out.println(sum2(10,20,30)) ;
System.out.println(sum(10,20,30)) ;
System.out.println("------------------") ;
//System.out.println(sum3(10,20,30,40)) ;
System.out.println(sum(10,20,30,40)) ;
System.out.println(sum(1.34,2.35)) ;
}
//定义两个数据之和的方法
public static int sum(int a ,int b){
return a + b ;
}
//一模一样的方法:方法名相同,参数类型都一样:重复定义!
/*
public static int sum(int a ,int b){
return a + b ;
}
*/
public static double sum(double a,double b){
return a + b ;
}
//定义三个数据求和的方法
//public static int sum2(int a,int b,int c){
public static int sum(int a,int b,int c){
return a + b + c ;
}
//定义四个数据求和的方法
//public static int sum3(int a,int b,int c ,int d){
public static int sum(int a,int b,int c ,int d){
return a + b +c + d ;
}
}
四.数组
1.定义:
- 数组是存储同一数据类型多个元素的集合,也可以看成是一个容器
- 数据既可以存储基本数据类型,也可以存储引用数据类型
2.格式
- 数据类型[] 数组名称;
- 数据类型 数组名称[] ;
3.初始化化:
动态: 指定数组长度,系统默认给元素分配值
- 数据类型[] 数组名称 = new 数据类型[数组长度] ;
- 数据类型 数组名称[] = new 数据类型[数组长度] ;
静态:直接指定了元素值,系统默认分配长度
- 数据类型[] 数组名称= new 数据类型[]{元素1,元素2,…} ;
- 数据类型 数组名称= new 数据类型[]{元素1,元素2,…} ;
静态初始化的简化格式:
- 数据类型[] 数组名称 = {元素1,元素2,元素3…} ;
- 数据类型 数组名称[] = {元素1,元素2,元素3…} ;
4.数组的遍历(规范格式)
class Array1{
public static void main(String[] args){
int[] arr = {1,2,3,4,5,6,7};
printArray(arr);
}
public static void printArray(int[] arr){
System.out.print("[");
//x表示角标,从0开始
for(int x=0;x<arr.length;x++){
//判断当角标达到最大时,输出元素同时,加上右中括号
if(x==arr.length-1){
System.out.println(arr[x]+"]");
}else{
System.out.print(arr[x]+" ,");
}
}
}
}
冒泡排序的实现
冒泡排序的思想:
两两比较,大的往后放,第一次比较完毕,最大值就出现在最大索引处!
规律:
两两比较,大的往后放
第一次比较:有0个不比
第二次比较:有1个不比
...
...
最终比较的次数:就是当前数组长度-1次
核心代码:
for(int x = 0 ; x < arr.length-1 ; x ++){//比较的次数
//内层循环:元素之间:两两比较,大的往后放
for(int y = 0 ; y < arr.length-1-x ; y ++){
//判断
if(arr[y] > arr[y+1]){
//中间变量
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp ;
}
}
}
5.内存分配
Java 程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
(1) 栈: 存储局部变量,被调用方法参数
- 优点:存储速度比堆快,仅次于寄存器,栈数据可以共享。
- 缺点:数据的大小和生存期必需确定,缺乏灵活性。
(2) 堆:存放由new创建的对象和数组
- 优点:可动态分配存储空间大小,Java垃圾回收器会自动收走不使用的数据
- 缺点:由于动态分配内存,存取速度较慢
(3) 方法区方法区中存放了每个Class的结构信息
(4) 本地方法区(和系统有关)
(5) 寄存器(供CPU使用)
五.多维数组
1.定义:就是元素为一维数组的一个数组。
2.初始化格式
格式1:
- 数据类型[][] 数组名 = new 数据类型[m][n];
- m:表示这个二维数组有多少个一维数组。
- n:表示每一个一维数组的元素有多少个。
格式2:
- 数据类型[][] 数组名 = new 数据类型[m][];
- m:表示这个二维数组有多少个一维数组。
- 列数没有给出,可以动态的给。这一次是一个变化的列数。
格式3:
基本格式:
- 数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2…},{元素1,元素2…},{元素1,元素2…}};
简化版格式:
- 数据类型[][] 数组名 = {{元素1,元素2…},{元素1,元素2…},{元素1,元素2…}};
说明:int[] arr = new int[3];
- 左边:
int:说明数组中的元素的数据类型是int类型
[]:说明这是一个数组
arr:是数组的名称- 右边:
new:为数组分配内存空间。
int:说明数组中的元素的数据类型是int类型
[]:说明这是一个数组- 数组长度: 其实也就是数组中元素的个数
3.遍历二维数组(规范格式)
//举例:二维数组:{{1,2,3},{4,5,6},{7,8,9}}
class lianxi42{
public static void main(String[] args){
int[][] arr={{1,2,3},{4,5,6},{7,8,9}};
printArray2(arr);
}
public static void printArray2(int[][] arr){
System.out.print("{");
//x表示数组的个数
for(int x=0;x<arr.length;x++){
System.out.print("{");
//y表示数组的长度
for(int y = 0;y < arr[x].length ; y++){
//每个数组中索引值最大的元素,且不是索引值最大的数组
if(y==arr[x].length-1 && x!=arr.length-1){
System.out.print(arr[x][y]+"}"+",");
}else if(y==arr[x].length-1 && x==arr.length-1){
System.out.println(arr[x][y]+"}}");
}else{
System.out.print(arr[x][y]+",");
}
}
}
}
}
六.面向对象
1.特点
- 更符合生活中的思想行为习惯
- 让我们从执行者变成了指挥者
- 把复杂的事情简单化
//测试类(有main()方法的即为测试类)
class StudentList{
public static void main(String[] args){
//创建对象操作
Student student = new Student("张三",20,"男","高三十八班");
//输出学生基本信息
System.out.println(student.name+"----"+student.age+"---"
+student.sex+"---"+student.sclass);
//[3]调用成员方法
student.sleep();
student.playgame("王者峡谷");
student.study();
}
}
class Student{
String name;
int age;
String sex;
String sclass;
public void study(){
System.out.println("他在学习");
}
public void sleep(){
System.out.println("她在睡觉");
}
public void playgame(String name){
System.out.println("他在"+name+"战斗");
}
//有参构造
public Student(String n,int a,String s,String sc){
name = n;
age = a;
sex = s;
sclass = sc;
}
注:[1]类名 对象名 = new 类名();
对象名可以自定义,括号为空,为无参构造,需要通过 对象名.变量名 = ---;按照形参类型合理赋值;
[2]先写基本类,再写测试类;基本类中 成员变量,无参构造,有参构造,成员方法
2.特征
//第一行包名自定义
public class Person {
//利用关键字private对成员变量进行初始化
private String name;
private int age;
private String gender;
//提供无参构造方法(Alt+shift+s---->c)
public Person() {
super();
}
//提供有参构造方法(Alt+shift+s---->o)
public Person(String name, int age, String gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
//提供公共访问方法(Alt+shift+s---->r)
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;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
注:super():父类的地址值引用(继承标志性关键字),这里是继承Objct类的无参构造,可以不写
setXxx(形参列表):遵循小驼峰命名法,用来赋值操作,在测试类中通过**对象名.setXxx(实参)**赋值;
getXxx():取值操作,在测试类中通过System.out.println(对象名.getXxx()),取值并输出;
快捷键:括号里面的为eclipse里面的快捷键,例如:Alt+shift+s---->r,就是同时按住Alt,shift,s键然后松开,再按个r键
注意:在测试类中,先赋值,再取值(先set再get)
2.2 继承
目的: 为了解决代码冗余问题,提高代码复用性,继承来了,将共有的属性或者方法通过继承共用
定义: 将多个类的共同具有的内容放到一个单独的类中,这些类与这个单独类具有继承关系
class Grandfather{
public void funtion(){
System.out.println("我是爷爷");
}
}
class Father extends Grandfather{
public void method(){
System.out.println("我是爸爸");
}
}
class Son extends Father{
String name;
//无参构造
public Son(){}
//有参构造
public Son(String name){
this.name = name;
}
public void ff() {
System.out.println("本尊");
}
}
public class ExtendTest {
public static void main(String[] args) {
Son son = new Son();
son.method();
son.ff();
son.funtion();
}
}
注:
[1]class 类名 extends 父类名 {}
这是一个子类,继承父类,子类具有父类的属性和方法;
[2]构造方法:为了数据初始化而诞生;
书写:权限修饰符(例如public) 方法名与类名完全一致 {------------}
分类:无参构造,有参构造;
顾名思义,有形参即为有参构造,无形参则无参构造,
有参构造的形参类型与成员变量的数据类型保持一致;
[3]如果形参变量名与成员变量名一样(即就是局部变量与成员变量),这时候,this关键字诞生了;
this:本类对象的地址值引用,而this.变量名 就表示当前类的成员变量;
成员变量与局部变量的区别;
1.书写位置
- 成员变量:位于类的内部,方法外
- 局部变量:位于方法的声明和定义出
2.内存位置
- 成员变量:在堆内存
- 局部变量:在栈内存
3.生命周期
- 成员变量:随着对象的创建完毕而存在,随着对象被Gc回收而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
4.初始化
- 成员变量:可以不用初始化,系统默认初始化
- 局部变量:必须初始化,否则会报错,可以先定义后初始化,也可以直接初始化
super关键字与this关键字的区别
1.定义
super:父类对象地址值的引用
this:本类中的地址值引用
2访问成员
super.变量名表示父类的成员变量
this.变量名表示当前类的成员变量
super()表示引用父类的无参构造方法,有形参即为有参构造
this()指向本类的无参构造方法,同上
super.方法名:表示父类的对应方法
super.方法名:表示当前类的对应方法
--------------------------------------------------
2.3多态
定义: 一个事物在不同时刻呈现出不同的状态;
前提条件:在继承的前提下,重写父类方法,父类引用指向子类对象;
public class AnimanTest {
public static void main(String[] args) {
//向上转型
Animal a1 = new Cat();
//调用static修饰的方法
AnimalTool.method(a1);
System.out.println("-----------------------");
a1 = new Dog();
AnimalTool.method(a1);
System.out.println("-----------------------");
Cat c1 = new Cat();
c1.drink();
System.out.println("-----------------------");
}
}
class AnimalTool{
private AnimalTool() {}
public static void method(Animal a) {
a.eat();
a.sleep();
}
}
class Animal{
//方法重写
public void sleep() {
System.out.println("吃");
}
public void eat() {
System.out.println("睡");
}
}
class Cat extends Animal{
public void sleep() {
System.out.println("吃鱼");
}
public void eat() {
System.out.println("站着睡");
}
public void drink() {
System.out.println("喝水");
}
}
class Dog extends Animal{
public void sleep() {
System.out.println("吃肉");
}
public void eat() {
System.out.println("躺着睡");
}
}
注:[1]向上转型,父类引用指向子类对象的体现
父类名 父对象 = new 子类名 子类对象
[2]方法重写:子类继承父类的过程中,子类出现了和父类一模一样的方法;
即就是父类和子类的方法完全一致, 访问同一方法时,父类的方法就会被子类方法覆盖
[3]方法重载:方法名相同,形参列表(形参个数,形参类型)不同,与返回值无关
[4]static关键字见下
多态的成员访问特点:
- 成员变量:编译看左,运行看左
- 成员方法:编译看左,运行看右(方法重写)
- 静态方法:编译看左,运行看左
- 构造方法:分层初始化
static关键字
- 随着类的加载而加载
- 优先于对象而存在
- 可以被多个对象共享共用
- 修饰成员变量,成员方法,一般方法时候可以通过类名直接调用
3.抽象类
- 有抽象方法(被bastract修饰)的一定是抽象类
- 抽象类不一定有抽象方法
- 没有抽象的方法不一定不是抽象类
引入:一个类的方法的内容不够具体,或者方法中内容为空,可以把这个类定义为抽象类;
abstract class Fu{
public abstract void method();
}
class Zi extends Fu{
@Override
public void method() {
System.out.println("子方法");
}
}
public class Test {
public static void main(String[] args) {
Fu f = new Zi();
f.method();
}
}
注:抽象类,抽象方法必须带abstract,定义为抽象方法后,如果继承自该抽象类,
则会强制重写(@Override);
4.接口
接口就是一个新加的功能,用类实现接口,多接口;
interface Jump{
//成员变量默认被final修饰,是一个常量
int i = 2;
void jump();
}
class Cat implements Jump{
//重写接口方法
@Override
public void jump() {
System.out.println("猫会跳高");
}
}
//测试类
public class Test2 {
public static void main(String[] args) {
//不能直接实例化,需要通过接口多态实现
Jump j = new Cat();
System.out.println(j.i);
j.jump();
}
}
注:implements:表示实现接口
interface:接口的关键字
一个类可以继承另一个类的同时,实现多个接口
final:表示最终的,不可更改的
final关键字
- 修饰变量时,变量成常量
- 修饰类时,该类不能被继承
- 修饰成员方法时,该方法不能被重写
抽象类与接口的区别
成员区别:
抽象类:
成员变量可以是常量也可以是变量
成员方法可以是抽象方法,也可以是一般方法
构造方法可以是有参构造也可以是无参构造
接口:
成员变量成了常量
成员方法只能是抽象方法
没有构造方法
关系区别:
类与类之间: 支持单继承,不支持多继承,支持多层继承
类与接口之间; 在继承一个类的同时可以实现多个接口
接口与接口之间: 存在继承关系,支持单继承,也支持多继承
设计理念:
抽象类------>继承关系-------->体现"is a"关系
接口------>体现额外功能----->是一种"like a"
5.内部类
定义:在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
5.1成员内部类
//外部类
class Circle {
double radius = 0;
public Circle(double radius) {
this.radius = radius;
}
//内部类:位于成员位置
class Draw {
public void drawSahpe() {
System.out.println("drawshape");
}
}
}
//测试类
public class Test3 {
public static void main(String[] args) {
Circle.Draw d = new Circle(2).new Draw();
d.drawSahpe();
}
}
注:[1]访问成员内部类的方法,通过 外部类名.内部类名 对象名 = 外部类对象.内部类对象();
[2]内部类可以直接访问外部类方法,变量;
[3]如果成员内部类方法是静态方法时,通过外部类名.内部类名 对象名 = new 外部类名.内部类名();
[4]当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下
访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
5.2局部内部类
//外部类
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
//局部内部类:方法中,即局部位置
class Woman extends People{
int age =0;
}
return new Woman();
}
}
注:局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private
以及 static 修饰符的。
5.3匿名内部类
abstract class Teacher{
public abstract void method();
}
class TeacherDemo{
public void show (Teacher t) {
t.method();
}
}
public class TeacherTest {
public static void main(String[] args) {
TeacherDemo t = new TeacherDemo();
t.show(new Teacher() {
@Override
public void method() {
System.out.println("好好学习,天天线上");
}
});
}
}
注:抽象类不能直接实例化,可以借助匿名内部类可以作为实参进行实例化;
interface Smoke{
abstract void show();
}
class Outer2{
public static Smoke method() {
return new Smoke() {
@Override
public void show() {
System.out.println("好好学习,,,");
}
};
}
}
public class StudentList {
public static void main(String[] args) {
Outer2.method().show();
}
}
注:类名直接方法,有static方法,可以访问show方法,method方法返回值类型为接口对应的Smoke;
接口作为返回值类型,return一个匿名内部类对象
附:选择排序
public class SelectSort {
public static void main(String[] args) {
int[] arr = {10,9,12,6,8};
paixu.xuanze(arr);
paixu.printArray(arr);
}
}
class paixu{
public static void printArray(int[] arr) {
System.out.print("[");
for(int x = 0;x<arr.length;x++) {
if(x==arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+",");
}
}
}
public static void xuanze(int[] arr) {
for(int x =0;x<arr.length-1;x++) {
for(int y =x+1;y<arr.length;y++) {
if(arr[y]<arr[x]) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
}
}
分析:索引为0对应的数,和其他的比较(索引为1以及之后),小的往前放,第一次比较完毕,
最小的就出现在了最小索引处;
索引为1对应的数,和其他的比较(索引为2以及之后),小的往前放,第二次比较完毕,
-----------------------
-----------------------------------------------------------------
发现:每次比较都是和其后一位先开始,然后一直到最后一个;