JavaSE 第二次学习随笔(二)

 

循环结构中的多层嵌套跳出

targeta:
for(int i = 0; i < 100; i++){
	for (int j = 0; j < 100; j++) {
		if(i + j == 100){
//			break targeta;
			continue targeta;
		}
	}
}

  

数组

* 一维数组里边存的是值(直接数据) 二维数组里边存的是一维数组的地址
* 二维数组和一维数组一样都是数据类型 二维数组类型的构成: 数据类型 + [] + [] 创建格式 type [][] name = new
* type[count][count_1]; count 是表示一维数组个数 count_1
* 是二维数组对一维数组的长度的建议值(可以不写的啦)!!!!如果有一维数组长度和它不一样长那么其不会生效

int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int[] b = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4 };

int[][] c = new int[2][];
c[0] = a;
c[1] = b;

for (int i = 0; i < c.length; i++) {
	int[] js = c[i];
	for (int j = 0; j < js.length; j++) {
		int num = js[j];
		System.out.print(num);
	}
	System.out.println();
}

  

增强for循环 : foreach 开始循环后从数组中取出第一个元素放入:前边的 变量中 使用其对 : 后边的 数组进行迭代

for (int[] is : c) {
	for (int i : is) {
		System.out.print(i);
	}
	System.out.println();
}

  

学会了循环 就可以学习排序啦~ 排序完就可以使用二分查找了呢

        // 冒泡排序
	public static int[] bubbleSort(int[] arr) {
		int sum = 0;
		for (int i = 0; i < arr.length - 1; i++)
			for (int j = 0; j < arr.length - i - 1; j++)
				if (arr[j] > arr[j+1]) {
					arr[j+1] ^= arr[j];
					arr[j] ^= arr[j+1];
					arr[j+1] ^= arr[j];
					sum++;
				}
		System.out.println(sum);
		return arr;
	}
     //选择排序
	public static int[] selectSort(int[] arr) {
		int sum = 0;
		for (int i = 0; i < arr.length - 1; i++)
			for (int j = arr.length - 1; j > i; j--)
				if (arr[i] > arr[j]) {
					arr[i] ^= arr[j];
					arr[j] ^= arr[i];
					arr[i] ^= arr[j];
					sum++;
				}
		System.out.println(sum);
		return arr;
	}

	
	public static int[] binaryFind(int[] arr, int num) {
		int startIndex = 0;
		int endIndex = arr.length;
		int middleIndex = 0;
		int index = -1;
		while (endIndex - startIndex >= 0) {
			middleIndex = (endIndex + startIndex) >> 1;
			int sBound = middleIndex - 1 > 0 ? middleIndex - 1 : 0;
			if (num >= arr[sBound] && num <= arr[middleIndex]) {
				index = sBound;
				break;
			} else if (num > arr[middleIndex]) {
				startIndex = middleIndex + 1;
			} else if (num < arr[middleIndex]) {
				endIndex = middleIndex - 1;
			}
		}
		int arr1[] = new int[arr.length + 1];
		int j = 0;
		for (int i = 0; i < arr.length; i++) {
			arr1[j++] = arr[i];
			if (i == index)
				arr1[j++] = num;
		}
		Arrays.toString(arr1);
		return arr1;
	}

  

接下来就要开始面向对象了, (牢骚 : 我还有对象, 可惜她不在我身边, 有些想她了, 虽然有好友在身边还是有点空落落的)

* 面向对象初识
* 开发的过程:不断的创建对象, 使用对象, 指挥对象做事情.设计类就是在管理和维护对象之间的关系
* 面向过程强调的是功能行为,注重解决问题的步骤
* 面向对象封装功能道对象里, 强调了具备功能的对象,关注的是解决问题需要哪些对象
* 面向对象更加符合人类的思维方式, 使得程序员从执行者变为指挥者
* 面向对象比面向过程更加高级
* 面向对象和面向过程都是一种编程思想
* 面向对象基于面向过程

 

* 对于类, 拥有相似功能和特性的事物可以抽象成一个类
* 对于类的对象的方法调用后系统直接释放它
* 对于类的对象使用完后,系统会调用gc之后释放他

 

* 成员变量的特点
* 创建对象的时候被赋予默认值
* 可以在类中定义对象的时候直接赋值
* 可以在没有被static修饰的方法中直接使用

* 成员变量和局部变量的比较
* 作用域 成员变量的作用域是类的对象, 局部变量的作用域是方法
* 默认值 成员变量有默认值, 局部变量没有默认值必须先初始化才能使用
* 释放机制 成员变量和类保持一致 局部变量使用完立即释放(局部变量和方法的生命周期是一样的ma ?)
* 存放机制 成员变量放在堆区中的对象中 局部变量放在栈区中的方法中
*
*
* 成员变量分成静态的和非静态的 (static)
* static : 静态成员和方法
* 非 static : 非静态成员和方法
* 静态的成员变量和放方法可以用引用调用也可以用类名调用
* 非静态的成员变量和方法只能用引用调用

 

事实上构造方法也是个static方法

* 调用构造方法的构成: 类名+()
* 作用: 对对象的属性进行初始化, 在没有自定义构造方法时, 能调用系统默认的无参构造方法
*
* 自定义类的构造方法:
* 无参 + 有参
*
* 基本构成 : 修饰词 方法名 参数列表 方法体
* 无返回值, 和类名相同
*
* 一旦自定义类的构造方法 系统就不会再有默认构造方法
* 构造方法的内部会自动的进行属性的初始化
* 多个构造方法之间是重载的关系
*
* 无参构造方法会将成员变量初始化成null或者0或者false等
* 有参构造方法会将成员变量进行初始化并赋值, 赋值成通过参数传入的值
* 有参方法中当方法形参和成员变量名字一致时, 方法内部是别的时形参 依据的时就近原则,
* 就近原则时说从内存的角度考虑的就近原则
*
* 对于类: this是一种引用类型, 是一种引用数据类型, 代表的是当前的对象, 保存的是当前对象的地址
* 在类内需要拿到当前类的引用的时候使用this.
*
* this 的作用 :
* 区分成员变量和局部变量
* 在构造方法中调用其他的重载的构造方法, 提高代码的复用性, 简化代码
*
* 通过this调用其他方法的时候必须放在当前方法的第一行
* 不能相互调用会造成死循环
* this() 作为方法只适用于构造

 


Java中程序的 .java 程序的基本运行过程 (https://blog.csdn.net/Marvel__Dead/article/details/69220153?locationNum=5&fps=1)
>> javac example.java >> java example.class >> jvm 调用ClassLoader 将example.class 加载到方法区, 当类被执行的时候 以main 方法作为入口
进入execute 子系统 >> 任何方法在被线程调用时都会在栈区开辟新的内存空间 所以在多线程环境下方法的执行是互不干扰的, 但是成员变量是存储在堆区
所以他们之间会互相干扰; >> 当在方法中有新建的对象时, 通过ClassforName(xxx.xxx.xxx).newInstance();创建类的过程是查看方法区是否有相应的.class 文件,
如果有就用 newInstance创建对象, 没有就通过类的全路径加载 .class 然后再创建对象(new 出来的对象在堆中);

对于类里边的静态成员变量和静态成员方法, 其存储在方法区, 静态成员变量存在于方法区的静态域中, 静态方法则存在于类的 .class 二进制信息中(.class 
中的二进制信息和方法区中的不一样, 读取.class 文件按照jvm需要的格式存储在方法区, 这种格式包括数据结构方面), 静态成员变量和静态方法使用时不用创建对象, 
类加载初始化后就可以使用, 并且线程是共享的

在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈 ,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因

 

 

* 静态代码块: 随着类的加载而加载, 在整个程序的过程中只执行一次,执行顺序优先级最高(高于main)
* 构造代码块: 随着类对象的加载而记载每次创建对象都会执行一次
* 静态代码块: 做类的初始化工作
* 构造代码块: 做对象的初始化工作

 

final:
1,修饰类,变量(成员变量,静态变量,局部变量),函数。
2,修饰的类不可以被继承。
3,修饰的函数不可以被重写。
4,修饰的变量是一个常量,只能赋值一次。
5,使用final修饰符不仅会保持对象的引用不会改变,而且还会保护这个对象在回调方法中的生命周期,所以这才是final修饰变量和final修饰参数的根本意义
final修饰的变量只能被赋值一次;由于赋值方式机制的不同因此分为两种情况:
成员变量:由于分配内存后系统自动赋初值,这样使得此变量失去意义,因此在定义成员变量时需要赋值,或者在代码块,构造器中对其赋值
局部变量:没有赋值,系统并不为它分配,栈内存,所以可以定义时可以赋值也可以不赋值,但是,形参作为局部变量,系统当将形参传递时已经赋值了所以,形参不能再
次改变.
宏变量:一个变量被final修饰且是编译时确定的。那么这个变量可称为宏变量。宏变量可以将引用指向常量池。
(https://blog.csdn.net/gcw1024/article/details/51026840/ )  常量池

 

程序中出现的不希望出现的数据为脏数据
出现原因直接给变量赋值
解决方案: 将成员变量变为private变量通过方法间接访问他;

封装: (根据属性的封装来说明) 把成员变量的访问进行私有化, 通过一个公共的方法对其进行访问.好处: 提高了访问的安全性代码的可复用性易读性
在方法内部先过滤再赋值

继承
*特殊类的对象拥有一般类的全部属性与行为,称为特殊类对一般类的继承。一个类可以是多个一般类的特殊类,也可以从多个一般类中继承属性与行为,但在java语言中,不允
*许一个类从多个一般类中继承属性与行为,即在java语言中,只支持单继承。
  *在软件开发中,通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。因此,类的继承性使
*所建立的软件具有开放性开放性、可扩充性,这是信息组织与分类的行之有效的方法,通过类的继承关系,使公共的特性能够共享,简化了对象、类的创建工作量,增加了代码
*的可重用性。
*重写
*构造方法中默认自动调用super();
* 在继承中使用构造方法
*
* *
* 1.当一个子类中只有一个带参数的构造方法,只能使用带参数的,不能使用无参的.如果想使用,必须手动建立无参的构造方法
* 2.当父类中只有带参数的构造方法,子类的构造方法中就必须在第一行手动调用父类带参数的构造方法(super(参数))
* 3.当我们创建构造方法的时候,如果自己不写super(),系统会自动调用
* 原因:父类中也有属性要进行初始化,而对象的属性必须由自己的构造方法进行初始化,所以必须调用super(),所以每个构造方法中都默认有一个super()
*
* 为什么要将super放在方法的第一行?
* 答:在子类的构造方法中有可能用到父类的属性,而属性在使用之前必须先进行初始化,否则无法使用.
*
* 总之:在继承体系中,作为父类最好的办法就是将无参构造方法和有参构造方法都写了.
* 重写:当子类有与父类同名(方法名,参数等完全相同)的方法,我们称为重写.
* 注意点:相当于子类的同名方法将父类的覆盖了,不会再去调用父类的方法.
*
* 作用:在不改变父类方法名字的前提下,在父类原有方法的功能基础上,实现一些自己的功能.实现了对原有功能的扩充.
*
* this:是一种引用数据类型,代表当前的对象.保存的是当前对象的地址
* super:不是一种引用数据类型.可以通过super调用父类的成员
*
* 注意事项:
* 1.私有方法不能被重写
* 2.子类的同名方法的权限大于等于父类的同名方法
* 3.静态的方法只能覆盖静态的方法

* 接口 interface
* interface 接口的名字{
* 成员变量默认 public final static
* 成员方法默认 public abstract
* 一般接口中不写成员变量, 只写方法和规则 又将接口称为方法列表
* 需要子类实现方法
* 继承 extends
* 实现 implements
*
* 接口本身时抽象的
*
* 接口和继承同时存在
* 接口自身可以多继承
* 接口可以被多实现
* 抽象类也一样可以impl接口
*
*
* 父类中放入主要功能
* 接口中放的是额外功能是类的补充 对类的方法行为的规定
* 接口不能被实例化 它默认是抽象的
* 接口与接口之间可以有继承的关系
*
* 一个类的接口中出现了相同的方法,子类实现时不会混淆,接口中的方法都是抽象的,只能通过子类具体实现, 该功能的实现只有子类中的一份;
*
*
* 接口的作用: 将Java从单继承间接的实现多继承,扩充了原来的功能, 我们可以认为接口是类的补充.
* jdk 1.7开始, 接口中可以有static或default 方法的实现

 

 

* 多态下的向上转型和向下转型(向父类转型, 和向子类转型)
*
* 向上转型:子类对象->父类对象 安全
* 向下转型:父类对象->子类对象 不安全
* 向上转型: 相当于自动类型转换, 由低类型到高类型, 由子类型到父类型
* >> 将子类类型引用(此引用指向的子类对象)转换成父类类型
* 向下转型: 相当于强制类型转换, 由高类型到低类型
* >> 将父类引用(此引用指向子类对象)转换成子类类型
* Object str = new String();
* ((String)str).toCharArray();

* /---Object Height
* | |
* | |
* -> Anmial |
* | |
* | |
* ----> Dog, Cat Low
* 类型Tree
* //前段时间写错了
* 一句话解释下边的错误:
* Object obj = new Object();
* (String)obj;
* 这不是多态 也不存在向下转型
*
*
* sysout(a instanceof B); a是B或B的子类对象 就是true 否则就是false (也就是说a类型必须大于等于b)
* 此关键字 a的引用类型 和 B 要有继承关系(前后位置没问题) 如果没有关系立刻报错

*
* class Son extends Person{...}
* Person s = new Son();
*
* 在多态下成员的使用方法: 其会根据引用类型调用方法除非强制类型转换
* 成员变量: 编译时能不能访问看父类, 运行时也看父类
* 成员方法: 编译时看父类, 运行时看子类
* 静态方法: 编译运行都看父类-->静态方法从属于类啊 所以它和子类没关系吧(直接用类名调用的哇)
*
* 总结: 多态情况下 只有 >>普通成员方法<< 最特殊 编译的时候由于Java 仅仅是准动态语言所以在此时编译阶段对象还没装入内存, 因此
* 方法能不能调用要看其引用类型中有没有这个方法
* 运行时: 对象已经装入内存我们实际操作的已经是该对象了(子类类型)
*
*
* ( https://www.zhihu.com/question/19883873)
* 为什么Java没有做成动态语言(准动态语言)?
* 静态类型有利于工具做静态分析,有利于性能优化,有利于代码可读性
* 越是复杂的项目,使用静态语言可以利用编译器更早的发现和避免问题。
* 这并不是说动态语言并不能用于大型项目,但是在超过一定规模之后, 动态语言轻便灵活的优势就会被重构时的overhead给抵消掉。
* 另一个原因是性能上的。同理,也不是动态语言写不出高效的代码,而是你花在优化上的时间会更多,
* 而团队人多了水平难免参差不齐,不如静态语言稳妥。

内部类
当 类C 同时需要实现A的功能 和B的功能时 可以建一个内部类 AA 对 A继承 BB对B继承 从而间接实现多继承
局部内部类
定义 : 在一个类的方法中的类
作用 : 可以将功能在类中私有化, 整理代码, 提高复用性
意义 : 对于被封装的方法, 相当于将他的一部分功能面向对象了
了解 :
例子 : 对于类中的方法a() 和 b() 和c() 想要对 b() 屏蔽 c() 方法[即b()无法调用c()]
只允许a()运行c(), 此时 将 c() 封装到 a() 中的局部内部类中

class Test{
	void a(){
		class C{
			void c(){}
		}
	}
	void b(){
	}
}

  


TIP:
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能。
局部内部类访问局部变量的注意事项
A:局部内部类访问局部变量必须用final修饰(1.7 之前)
B:为什么呢?
因为局部变量会随着方法的调用而调用,随着调用完毕而消失。
而堆内存的内容并不会立即消失。所以,我们加final修饰
加入final修饰后,这个这变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。

 

posted @ 2018-08-06 13:05  一根咸鱼干  阅读(364)  评论(0编辑  收藏  举报