Java学习笔记(四)
区分全局变量和局部变量
局部变量 | 全局变量(成员变量) | |
---|---|---|
定义位置 | 定义在方法/if/for等里面 | 定义在类里面的 |
作用域 | 从定义开始到所在的方法/if/for等结束 | 整个类 |
内存中存储位置 | 存贮在栈区中加载的方法中 | 在堆区中的对象里面 |
释放机制 | 使用完立刻释放 | 随对象的回收一并回收 |
默认值 | 没有默认值,所以在使用前必须先赋值 | 有默认值,整数–0,Boolean-false,浮点–0.0,引用数据类型–null |
package com.qf.note;
public class Note12 {
//全局变量
int age;
public static void main(String[] args) {
int a = 3;//局部变量
for(int i = 0; i<5;i++){//局部变量
//局部变量
int b = 6;
b+=4;
}
if(a>5){
//局部变量
int c= 7;
System.out.println(c);
}
Note12 note12 = new Note12();
System.out.println(note12.age);//调用age--0
}
//形参也是局部变量
public void show(int x,int y){
System.out.println(x);
System.out.println(age);
}
}
Arrays的使用
比如:Arrays是操作数组的一系列方法
Collections:操作集合的一系列方法
Files:对File类进行的再封装
Paths:对Path类进行的再封装
package com.qf.note;
import java.util.Arrays;
public class Note13 {
public static void main(String[] args) {
int[] arr1 = {2,4,65,78,6};
//copyOf(int[] array, int newLength)
//从原数组中拷贝指定数量的元素,到一个新的数组中,并返回这个新的数组
int[] newArr = Arrays.copyOf(arr1,arr1.length+1);
newArr[newArr.length-1] = 5;
System.out.println(Arrays.toString(newArr));
//copyOfRange(int[] array, int from, int to)
//从原数组中拷贝指定范围 [from, to) 的元素,到一个新的数组中,并返回这个新的数组
int[] newArr2 = Arrays.copyOfRange(arr1,1,2);
System.out.println("copyofRange:"+Arrays.toString(newArr2));//[4]
//sort():内部使用的是快排和归并
Arrays.sort(arr1);
System.out.println("arr1:"+Arrays.toString(arr1));
//查找:binarySearch(int[] array, int element)---数组必须先有顺序
int index = Arrays.binarySearch(arr1,65);
System.out.println("index:"+index);
}
}
创建类
实例:创建人类
有三要素:类名,属性,行为
属性---成员变量描述
行为---成员方法描述
class 关键字,专门用来定义类的
class 类名{
属性
行为
}
package com.qf.note;
public class Note14 {
public static void main(String[] args) {
//测试
//创建对象
int[] arr = new int[4];
//解释:使用Person类型的变量p存储Person对象的地址
//new 是在堆中开辟一块空间,并将地址返回
//Person()是一个空参的构造方法,专门用来对对象的属性进行初始化,赋初始值
Person p = new Person();
//通过点语法
//给成员变量赋值
System.out.println(p.age);//0
p.age = 10;
p.name = "bing";
System.out.println(p.name);
System.out.println("p.height:"+p.height);
//调用方法
p.eat();
p.play();
}
}
class Person{
//成员变量
int age;
String name;
int height = 5;//直接赋值
//成员方法
public void play(){
System.out.println(name+"在play");
}
public void eat(){
System.out.println(name+"在eat");
}
}
匿名对象
可以作为方法的参数,简化代码,提高程序执行的效率,使用垃圾回收机制回收的是没有指向对象(实体),当我们使用匿名对象时,将功能完成,对象就没用了,可以快速通过垃圾回收机制回收.
package com.qf.note;
public class Note15 {
public static void main(String[] args) {
// Dog dog = new Dog();
// dog.name = "拉布拉多";
//直接使用对象工作
//没有指向的对象我们称为匿名对象
//匿名对象可以工作,但是调用一次之后,就变成了垃圾,无法再次使用
new Dog().name = "金毛";
new Dog().age = 20;
new Dog().name = "小黄";
//使用匿名对象传参
//Dog dog = new Dog();
show(new Dog());
}
public static void show(Dog dog){
dog.eat();
}
}
class Dog{
int age;
String name;
public void eat(){
System.out.println("狗吃饭");
}
}
构造方法
功能:对对象的属性进行初始化
解释:系统会默认生成空参的构造方法,用于属性的初始化,但是一旦用户自己手动生成构造方法,系统就不再自动生成构造方法.
构造方法的语法构成:
修饰词 方法名(参数列表){
方法体
}
注意点:
1.构造方法没有返回值这一项
2.构造方法的名字必须与类名一至
手动生成构造方法的作用:希望在对属性进行初始化的同时完成赋值—写带参数的构造方法
为了提高方法使用的效率,一般我们会直接将参数的名字与属性的名字一致.
this总结:
1.识别同名的成员变量和局部变量
2.作为构造方法调用,可以简化代码
注意点:
- 1.不能自己调用自己—死循环
- 2.不能相互调用----死循环
- 3.this充当构造方法时,必须放在第一行
- 4.this在作为方法的时候,只能充当构造方法,不能作为其他方法
- 5.this的使用范围就是当前类的内部
- 6.只有在非静态方法中,才可以使用this.
package com.qf.note;
public class Note16 {
int age;
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "波斯猫";
cat.play();
Cat cat1 = new Cat(2,"家猫");
System.out.println(cat1.name);
}
public void show(){
}
}
class Cat {
int age;
String name;
int height;
int weight;
public void play() {
System.out.println("play");
}
public Cat() {
//会自动对属性初始化
System.out.println("空参构造方法");
}
/**
* 对属性进行初始化的同时完成赋值
*
* @param age 年龄
* @param name 姓名
*/
//为了提高方法使用的效率,一般我们会直接将参数的名字与属性的名字一致.
/*
如果在同一个方法内部识别出了两个同名的变量(一个全局的一个局部的),优先识别局部变量.所以无法完成对全局变量的赋值
我们将这种情况称为就近原则:在程序执行时,内存中变量与方法的距离,谁离得近识别谁.
解决:
通过关键字 this,强行识别成员变量
this:是关键字,是一种引用,指向当前的对象,保存当前对象的地址.通过this.成员变量识别
*/
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
public Cat(int age,String name,int height,int weight){
// this.age = age;
// this.name = name;
//通过this构造方法调用有两个参数的构造方法
//1.this作为构造方法必须放在第一行
//System.out.println("hello world"+this.age);
this(age,name);
this.height = height;
this.weight = weight;
}
}
package com.qf.note;
/*
- 定义:我们可以通过对具体属性的封装实现.把对成员变量的访问进行私有化,让他只能在类内部可见,通过公共的方法间接实现访问.
- 优点:提高了代码的安全性,复用性和可读性.
*/
public class Note17 {
public static void main(String[] args) {
//实例:开枪射击
/*
对象:枪,子弹
*/
Gun gun = new Gun();
/*
- 脏数据:我们把程序中出现的不符合逻辑的数据称为脏数据
- 脏数据分析
原因:让用户直接将数据传给了成员变量
解决:我们自己要对数据进行过滤
1.不让他直接传值----将成员变量私有化,写一个公共的方法
2.对数据进行过滤,将过滤后的数据交给成员变量
*/
//gun.bulletNumber = -10;
gun.addBulletNumber(-10);
gun.shoot();
}
}
/*
因为往往我们会有大量的属性需要进行赋值取值操作,所以就形成了一个规范
- 赋值的规范:setter方法
构成:修饰词 返回值 方法名 (参数列表){
方法体中的代码
return 返回值
}
修饰词:一定是public
返回值:不需要,这里写void
方法名:set+属性的名字,名字的首字母大写
参数列表:一般只有一个,写法:与属性同名
代码:this.属性的名字 = 参数
return:不需要
- 取值的规范:getter
构成:修饰词 返回值 方法名 (参数列表){
方法体中的代码
return 返回值
}
修饰词:public
返回值:类型与属性一致
方法名:get+属性的名字,首字母大写
参数列表:不需要
代码:没有
return 属性的名字/this.属性的名字
*/
class Gun {
/*
private:范围修饰词,限制当前变量的使用范围是当前的类
*/
private int bulletNumber;
private int height;
private int weight;
private String name;
private int model;
//通过公共方法传值
public void addBulletNumber(int bulletNumber) {
//过滤
if (bulletNumber < 0) {
bulletNumber = 0;
}
this.bulletNumber = bulletNumber;
}
public int getBulletNumber() {
return bulletNumber;
}
public void setBulletNumber(int bulletNumber) {
this.bulletNumber = bulletNumber;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getModel() {
return model;
}
public void setModel(int model) {
this.model = model;
}
public void shoot(){
if (this.bulletNumber > 0) {
bulletNumber--;
}
System.out.println(bulletNumber);
}
public Gun(){}
public Gun(int bulletNumber, int height, int weight, String name, int model) {
this.bulletNumber = bulletNumber;
this.height = height;
this.weight = weight;
this.name = name;
this.model = model;
}
}
继承
继承:有两个类A,B,当A继承了B,我们就说他们有了继承关系
特点:子类可以无偿获取父类所有的成员,除私有的之外
重写
方法的重写:子类创建了与父类相同的方法,就是重写
作用:子类为了在实现父类方法基本功能的基础上实现一些自己的功能.
注意:
1.在重写时我们可以通过super调用父类同名方法的基本功能
2.子类重写方法的返回值可以与父类方法相同类型,也可以是父类方法返回值类型的子类
3.子类重写方法的修饰词可以与父类的相同,也可以子类的大于父类的范围
package com.qf.note;
public class Note18 {
public static void main(String[] args) {
Iphone iphone = new Iphone();
iphone.gui = "贵";//自己的属性
iphone.color = "黄色";//父类的属性
/*
方法调用的原理:首先会到自己的内部找callPhone方法,找到了执行,找不到,再继续到父类中查找,找到了执行,
找不到继续向上,一直找到Object,如果还是没有找到,就证明没有这个方法.
*/
iphone.callPhone();//父类的方法
}
}
//如果一个类继承自Object类,可以省略不写,默认就是继承自Object
class Phone extends Object{
String color;
String name;
public void callPhone(){
System.out.println("打电话");
}
//如果不写默认是default,不能是private
Phone test(){
return null;
}
}
//让Iphone继承自Phone
class Iphone extends Phone{
String gui;
public void fangshui(){
System.out.println("苹果功能");
}
//重写test方法
/*
注解:是有某种特殊功能的一种表示形式
@Override注解的作用:标注下面的方法是一个重写方法,如果不是,报错
*/
@Override
//子类重写方法的返回值可以与父类方法相同类型,也可以是父类方法返回值类型的子类
//子类重写方法的修饰词可以与父类的相同,也可以子类的大于父类的范围
public Iphone test() {
return null;
}
//重写的父类方法
public void callPhone(){
//System.out.println("打电话");
/*
super与this
this:表示当前的对象
super表示当前对象的父类
通过super直接调用父类的成员
*/
super.callPhone();
//this.callPhone();
System.out.println("自己的功能");
}
}
class HuaWei extends Phone{
String wuDi;
public void fangYou(){
System.out.println("华为特有-防油");
}
}
继承中使用构造方法
当我们创建构造方法的时候,为什么一定要调用super?
原因:父类中也有属性要进行初始化,而对象的属性必须由自己的构造方法进行初始化,所以必须调用super(),所以每个构造方法中都默认有一个super()
注意:super()要放在第一行,一定要保证属性先初始化再使用.
不能被子类继承的有什么?
private修饰的成员
构造方法
跨包子类
package com.qf.note;
public class Note19 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
class Fu{
int age;
public Fu(){}
public Fu(int age){
super();
this.age = age;
}
}
class Zi extends Fu{
public Zi(){
//第一行都默认有一行代码super(),调用的是父类空参的构造方法
//这是是因为找不到父类空参构造方法了
/*
解决:1.给父类同时生成有参和无参的构造方法
2.如果父类只有有参构造方法,子类就去直接调用这个方法.
*/
//super();
super(20);
}
}