第二章 面向对象
2.1 使用Scanner获取键盘输入
// 测试Scanner获取键盘输入
import java.util.Scanner;
public class TestScanner {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的名字");
String name = scanner.nextLine();
System.out.println("请输入你的爱好");
String hobby = scanner.nextLine();
System.out.println("################");
System.out.println(name);
System.out.println(hobby);
}
2.2 流程控制语句 (三种 顺序结构 选择结构 循环结构)
- 分类:
- 顺序结构 没什么好说的
- 选择结构 细分为四种
- If 单选择结构
- if else 双选择结构
- Ifelse-ifelse 多选择结构
- switch结构
public class TestChoice { public static void main(String[] args) { double d = Math.random();//取0-1的随机数 左闭右开区间[0,1) System.out.println(d); int e = (int)(6*Math.random()) +1; System.out.println(e); if(e>=3) { System.out.println("你掷出的数大于等于三"); }else { System.out.println("你掷出的数小于三"); } System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$"); //随机产生0-4 的半径 double r = 4*Math.random(); System.out.println(r); float PI = 3.14F; double area = PI*r*r; double cycle = 2*Math.PI*r;//Math 类中定义了pi常量 if(area>=cycle) { System.out.println("圆的面积大于周长"); }else { System.out.println("圆的周长大于面积"); } System.out.println("#################"); //switch 多值判断 break 跳出循环 结束了switch语句 int month = (int)(1+12*Math.random()); System.out.println(month); switch(month) { case 1://后面是:冒号 不是分号; System.out.println("现在是一月份了"); break; case 2: System.out.println("现在是二月份了"); break; default: System.out.println("我现在是其他月份了"); } } }
- 循环结构
- 按照结构进行分类:两种
- 当型
- 直到型
- 按照使用的关键字:
- while 型
- for型
- 循环 中break 和continue:
- break 用于强行退出循环,不执行循环中的剩余语句
- Continue 是跳出当次循环 继续下次循环
- 注意:可以用带标签的break 和 continue进行多层循环的跳转 类似goto
public class TestForWhile { public static void main(String[] args) { int i = 1; int sum =0; while(i<=100) { sum +=i; i++;//很重要 } System.out.println(sum);//while 型 先判断在执行 System.out.println("########################"); int m = 1; int n = 0; do { n +=m; m++; }while(m<=100); System.out.println(n);//do-while 型 先执行在判断 不常用了解就行 System.out.println("###########################"); int sum1 =0; for(int j = 1;j<=100;j++) { sum1 +=j; } System.out.println(sum1); System.out.println("###################"); //嵌套循环 for(int k = 1;k<=5;k++) { for(int L = 1;L<=5;L++) { System.out.print(k);//这里循环K L是不同的 循环L会输出12345 12345 12345 } System.out.print("\n");//或者是syso } //嵌套循环打印99乘法表 System.out.println("##############################"); for(int q = 1;q<=9;q++) { for(int p=1;p<=q;p++) { System.out.print(p+"*"+q+"="+q*p+"\t"); } System.out.println(); } } }
- 按照结构进行分类:两种
2.3 语句块 方法
- 块确定了局部变量的作用域 块中的程序代码 作为一个整体 是要被一起执行的
- 块可以嵌套 但是不能声明相同的变量名
- 方法就是一段用来完成特定功能的代码片段,类似于其它语言的函数
2.4方法的调用方式:
- 形式参数,在方法声明时用于接收外界传入的参数。
- 实参 调用方法时实际接受的数据
- 返回值 方法在执行完后还给调用它的环境的数据。
- 返回值类型 事先约定
- 注意:
- Java中的值传递都是传递的值的副本会事先拷贝一遍传递的是copy的值
- 引用拷贝是该对象的copy的值 但是指向同一个对象。
- java中只有值传递 没有引用传递(这一点非常的重要)
public class TestFunction { public static void main(String[] args) { //通过对象来调用普通方法 //直接调用printSc();是不可以的 TestFunction tf = new TestFunction(); tf.printSc(); tf.add(20, 60, 30);//调用的时候需要使用实参 int f = tf.adds(100, 130, 110) + 100; System.out.println(f); } void printSc() { System.out.println("我是上山打老虎"); } void add(int a,int b,int c) {//这里是形式参数 int sum = a+b+c; System.out.println(sum); } int adds(int a1,int b1,int c1) {//这里是形式参数 int sum1 = a1+b1+c1; System.out.println(sum1); return sum1;//return 有两个作用 一是 结束方法的运行 二是返回值 } }
2.5 方法的重载(overload)
- 重载的方法是完全独立的不同的方法,只是名称相同而已
- 重载 参数的类型 个数 顺序不同 都可以构成方法的重载
- 但是只有参数的名称 或是返回值的不同不相同是不能构成重载
System.out.println()//就是一个重载的方法
public class TestOverload { public static void main(String[] args) { add(1,2); add(1,2,3); } public static int add(int a,int b) { int sum = a + b; System.out.println(sum); return sum; } public static int add(int a,int b,int c) {//方法名相同,参数个数不相同,构成重载 int sum = a + b +c;//加static 可以直接调用 不用new对象 System.out.println(sum); return sum; } }
2.6 递归结构
- 递归的基本思想就是 “自己调自己”
- 两个要点:
- 定义递归头 没有头就会陷入死循环 也就是递归结束的条件
- 递归体就是什么时候需要调用自身的方法
- 注意:
- 递归是很占资源的 而且一般来说可以用递归的情况 就可以使用循环来解决
- 使用递归能使程序看起来非常简单清晰
public class TestRecursion { public static void main(String[] args) { a(); } static int count = 0; static void a() { System.out.println("a"); count++; //可以在方法中调用其他方法,也可以调用自己 if(count<=10) { a(); }else { return;//这里不能使用break 不是循环 } } static void b() { System.out.println("b"); } }
2.7 面向过程与面向对象
-
区别:
- 面向对象和面向过程都是解决问题的思维方式 也都是代码的组织方式
- 解决简单问题可以用面向过程。
- 解决复杂的需要协助的问题,宏观上使用面向对象,微观处理上使用仍然上是面向过程。面向过程与面向对象是相辅相成的
-
对象的进化史(数据管理与企业管理的共同之处)-- 量变引起质变
- 数据无管理时代
简单 变量少 就是几个 或者是几十个 - 数组管理和企业的部门制
没有复杂的管理问题 就需要归类—于出现了数组 - 对象和企业的项目制
什么都干 出现了对象 静态的特征和动态的行为
- 数据无管理时代
-
对象和类的概念
- 对象 内存块 里面会放一些数据与方法
- 类 class 类就是对象的模板
- 通过抽象产生类 然后程序运行产生对象object,instance实例
- 类中一般有两种东西 1 是成员变量(成员变量和属性严格区分是不一样的)2 是方法
public class TestClass {//类中一般有两种东西 1 是属性 (成员变量)2 是方法 //属性 int id; // 只有属性没有方法在c语言中叫做结构体 int age; String name; computer comp; //方法 void study() {//加上static修饰可以直接调用 而不用创建对象 不加不行 System.out.println("学生可以学习。使用的是"+comp.brand); } void play() { System.out.println("学生可以玩游戏。"); } //main 方法是程序执行的入口 必须要有 public static void main(String[] args) { TestClass stu = new TestClass(); stu.name = "王"; stu.age =118; stu.id = 1; computer c1 = new computer(); c1.brand = "雷神"; stu.comp = c1;//互相应用 将c1的属性赋给stu.comp stu.study(); stu.play(); } } class computer{ String brand;//品牌 }
- 类的深化
构造方法
就是用于创建类的对象 无参的构造方法可以由系统自动创建- 可以有多个类但是只能有一个由public修饰的类
public class TestConstructor { double x; double y; public TestConstructor(double _x,double _y) {//构造方法 这里使用的是this 能省略不写 x = _x; y = _y; } public double getDistance(TestConstructor p) {//这方法是获取两点之间的距离 return Math.sqrt((x-p.x)*(x-p.x)+(y- p.y)*(y-p.y)); } public static void main(String[] args) {//main方法 程序的入口 TestConstructor p = new TestConstructor(3.0, 4.0); TestConstructor origin = new TestConstructor(0.0, 0.0); System.out.println(p.getDistance(origin)); } }
-
类与类之间是可以嵌套的 也可以互相引用
- 面向对象的内存分析(堆 栈 方法区)
- Java虚拟机的内存分为三部分1 栈 stack 2堆 heap 3 方法区 method area
- 不同种的语言底层相似的 (学习语言:基础非常的重要!)
- 栈的特点如下:
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量,操作数,方法出口等)
- jvm(java虚拟机)为每一个线程创建一个栈,用于存放该线程执行方法的信息(实际参数,局部变量等)
- 栈属于线程私有,不能实现线程的共享
- 栈的存储特性是“先进后出 后进先出”
- 栈是由系统自动分配的,速度快!栈是一个连续的内存空间
- 堆的特点:
- 堆是用于存储创建好的对象和数据(数组也是对象)
- JVM只有一个堆,被所有线程共享
- 堆是一个不连续的内存空间,分配灵活,速度慢!
- 方法区的特点(又叫静态区)方法区也在堆中间 但是特殊
- JVM中只有一个方法区,被所有的线程共享!
- 方法区实际也是堆,只是用于存储类、常量相关信息
- 用来存放程序中永远不变的或者是唯一的内容(类信息【class对象】、静态变量、字符串常量等)
- 构造器也叫构造方法 (constructor)用于对象的初始化
- 要点:
- 要使用new关键字来调用
- 构造器虽然有返回值 但是不能定义构造器的返回值类型(返回值的类型一定是本类)不能再构造器中使用return返回某个值
- 如果没有定义一个构造器 则编译器会 自己自动定义一个无参的构造函数,如果已定义的则编译器不会添加
- 构造器的方法名必须和类名一致
- 要点:
- 垃圾回收机制(Garbage Collection)
-
作用:
- 发现无用的对象
- 回收无用对象的内存空间
-
垃圾回收的两种算法
- 引用计数法:有引用记为一没有引用记为NUll 就表示无用的对象 (优点是算法简单 但是不能识别循环引用的对象)
- 计数可达法(这种方式更加优秀)从一个节点上,将所有的结点寻找完毕之后,没有到达的就是无用结点
-
通用的分代垃圾回收机(年轻代 年老代 持久代)
- Jvm将内存分为Eden Survivor Tenured/old 空间
- Minor GC 用于清理年轻代的区域
- Major GC 用于清理年老代的区域
- Full GC 用于清理年轻代和年老代的区域 成本较高 会对系统的性能产生影响
- Jvm将内存分为Eden Survivor Tenured/old 空间
-
注意:system.gc 只是建议去调用gc 而不是去直接调用gc
-
- 面向对象的内存分析(堆 栈 方法区)
-
对象创建的过程与this的本质(用于指代当前方法所指代的对象)
- 创建一个对象有四步:(非常的重要先进行的是默认的初始化 在进行显式的初始化)
- 分配对象空间 ,并将对象的成员变量初始化为0 或是null
- 执行属性值的显式初始化
- 执行构造方法
- 返回对象的地址给相关变量
- this最常用的使用方式:
- 在程序中产生二义性之处,应使用this来指明当前对象, 普通方法中,this总是指向调用该方法的对象, 构造方法中, this总是指向正要初始化的对象
- 使用this关键字调用重载的构造方法,避免相同的初始化的代码,但只能在构造方法中使用,并且需要位于构造方法的第一句。
- 注意: this不能用于static方法中
- static关键字:
- 在类中,用static声明的成员变量为静态成员变量,也称为类变量,类变量的生命周期与类相同,在整个应用程序期间都有效。
- static修饰的成员变量和方法 从属于类,普通变量和方法从属于 对象
- 静态初始化块 :Java 中是值传递 传递的是值得副本
- 包机制 就是管理类的机制
- packge 的两个要点:
- 通常是类的第一句非注释性语句
- 域名倒着写
- packge 的两个要点:
- 创建一个对象有四步:(非常的重要先进行的是默认的初始化 在进行显式的初始化)