【JavaSE学习笔记】

JavaSE学习笔记

一、java的基本语法

变量运算规则

在这里插入图片描述
编码情况1中l后面没有加L,默认是int变量
编码情况2中b1=b+1中的1默认是int型变量,会出错

string类型

在这里插入图片描述
string里面可以从0个字符开始赋值,但是char的‘’里面至少有一个字符

在这里插入图片描述
如果“+”前后有一个数据类型是string类型,那么就是在做连接运算,如果两个都不是string类型,那就是在做加法运算

在这里插入图片描述
输出结果:
在这里插入图片描述
像下面的\t注意要用双引号,不能用单引号,不然就成了加法运算而不是连接运算
在这里插入图片描述

第二种全是char型变量,相加会输出int型变量,第四种前两个变量相加会输出int型变量
在这里插入图片描述
在这里插入图片描述
不可以把string类型的强制转为int型,只可以做连接运算


string类型在常量池中,重新定义一个对象,如果常量池有了,那么它会复用已存在的

String s1 = "BB";
String s2 = "BB";
System.out.println(s1 == s2);//true

之前用==判断String 不是判断常量池的内容 是用两个String类型的对象进行比较 那时候比较的是对象地址值 而不是内容!
注意区分字符串常量和字符串对象,一个指向常量池,一个指向堆中
所以后面在重写类的equals时注意比较string时要用string类自己重写的equals

			//正确的:
			return this.orderId == order.orderId && 
					this.orderName.equals(order.orderName);
			//错误的:
//			return this.orderId == order.orderId &&
//					this.orderName == order.orderName;

注意:在JDK6.0及之前版本,字符串常量池存放在方法区中在JDK7.0版本以后,字符串常量池被移到了堆中了

运算符

自增运算符不会改变本身变量的数据类型


在这里插入图片描述
编译失败的2是int型

在这里插入图片描述
在这里插入图片描述
*=也不会改变数据类型,也是输出int型,会截断输出0


在这里插入图片描述
最后一个是12的原因:前一个操作n已经变成了11,最后一个++n,先自增,所以+的是12


区别位运算符和逻辑运算符:位运算符前后都是数,逻辑运算符前后都是布尔型


在这里插入图片描述


==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否相同


三元运算符

:前后的两个类型要求是一致的
Integer与Double在三元运算符中先转换成int与double基本数据类型去做比较,返回的结果是double1.0会再转化成包装类赋给o1

	public void test1() {
		Object o1 = true ? new Integer(1) : new Double(2.0);
		System.out.println(o1);// 1.0,自动类型提升,所以输出1.0

	}

if-else

在这里插入图片描述
()里面不要这样写,80<score会生成一个bool类型,会报错
else if里面的条件表达式正确时,不会再执行下面的if-else了
在这里插入图片描述
else遵循就近原则,所以输出的是x
“是”.equals(str)函数判断.前面的字符是否和()里面的字符一样

switch case

在这里插入图片描述
一些合并的写法


三元表达式-if-switch之间的关系
都可以转换成if表达式,但是反之不成立
在这里插入图片描述


下面代码里面如果没有break的话,前面定义的money和info会延续到后面继续使用,一般来说支出金额要重新定义一个名字,eg:addMoney,minusMoney
在这里插入图片描述

循环

for循环里面的i只在for循环里面有效

二、数组

动态定长度,静态定元素
在这里插入图片描述
char数组:元素的默认初始化值是0,非‘0’,打印出来的效果跟空格一样,实际上并不是空格
空格对应的数值是32,空字符对应的数值才是0,字符’0’对应的数值是48

字符串属于引用类型

放在main函数中的变量都叫局部变量,局部变量放在栈当中

二维数组

定义时也可以像下面这样定义
在这里插入图片描述
下面是一些错误例子,前面的两个括号里面不能写数字,也不能动静态初始化混用
在这里插入图片描述
总结:
在这里插入图片描述
数组赋值是新开辟一个数组,进行每一个元素的赋值,而不是直接用新数组=旧数组来操作,这样只是指向地址相同

三、面向对象

值传递

和数组的情况类似,这种是地址赋值,修改属性值时其他指向同一个地址的类的属性值也会变化
在这里插入图片描述


arr数组调用的是println(Object)函数,输出地址值
arr数组调用的是println(char[])函数,这个函数的方法体里面是遍历输出的代码,所以不会输出地址值

在这里插入图片描述
在这里插入图片描述


这段代码输出的是hello,虽然string是引用数据类型,但是它比较特殊
原因:
string是引用数据类型,在常量池中创建了一个char型数组存放了hello,再将这个hello的地址值赋给了s1,接着将s1赋给了s,s和s1指向同一块地址,此时s1也指向hello的地址,因为string的底层是用char数组进行存放的,所以在给s赋值“hi~~”时,又会创建一个新的char数组,来存放“hi”将这个新char数组的地址赋给s,所以s1的指向依旧是hello,最终输出hello
在这里插入图片描述


封装性

封装性的体现:
四种权限也可以体现为封装性的一种
在这里插入图片描述


综合练习一:customer和account

Account是一个public的类,可以在另一个类中定义成一个属性,参考string,string也是一个类,它也可以这样定义
在这里插入图片描述
customer手上有账号account,每一个用户对应一个账户,所以在用户类里面又定义了账户类,通过用户类去操作账户类
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


import关键字

import static组合的使用:调用指定类或接口下的静态的属性或方法
表示import的是system下的一些静态属性或者方法原来的代码:
在这里插入图片描述

原来的代码:
out前面删掉了string
在这里插入图片描述

就可以改写成下面的写法
在这里插入图片描述
out是string类中定义的一个属性

在这里插入图片描述
import 和import static的区别:
import的落脚点是类
import static的落脚点是类中的一个结构

在这里插入图片描述


继承性

子类会继承父类中的所有属性和方法,但是能不能访问又是另外一回事了

方法重写

编译器认为int…和int[]是一样的,在方法重写时要注意


在这里插入图片描述
子类重写的方法的返回值类型必须是相同的基本数据类型(比如:double)


四种访问权限修饰符

在这里插入图片描述
在这里插入图片描述
总结:
1、对于在同一个包下的父类中的属性和方法,除了private修饰的,其他的都可以被子类调用;
2、对于不同包下的父类中的属性和方法,除了private和缺省修饰的,其他的都可以被子类调用;
3、对于不同包下的普通类(非子类),只能调用public


super

子类中的多个构造器中至少有一个构造器中用super(形参列表)

子类对象实例化

在这里插入图片描述
1).为什么super(…)和this(…)调用语句不能同时在一个构造器中出现?
因为二者都必须出现在首行
2).为什么super(…)或this(…)调用语句只能作为构造器中的第一句出现?
无论通过哪个构造器创建子类对象,需要保证先初始化父类。
目的:当子类继承父类侯,“继承”父类中所有的属性和方法,因此子类有必要知道父类如何为对象进行初始化

多态性

对象的多态性:在编译期,只能调用父类中声明的方法,但在运行期,实际执行的是子类重写父类的方法。多态是运行时行为,因为方法调用在编译器是无法确定的
属性不存在多态性
属性(编译和运行都看左边)


多态性的使用举例:
好处:减少了方法的重载

package com.atguigu.java4;

import java.sql.Connection;


//多态性的使用举例一:
public class AnimalTest {
	
	public static void main(String[] args) {
		
		AnimalTest test = new AnimalTest();
		test.func(new Dog());
		
		
		test.func(new Cat());
	}
	
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
		
		if(animal instanceof Dog){
			Dog d = (Dog)animal;
			d.watchDoor();
		}
	}
	
//	public void func(Dog dog){
//		dog.eat();
//		dog.shout();
//	}
//	public void func(Cat cat){
//		cat.eat();
//		cat.shout();
//	}
}


class Animal{
	
	
	public void eat(){
		System.out.println("动物:进食");
	}
	
	public void shout(){
		System.out.println("动物:叫");
	}
	
	
}

class Dog extends Animal{
	public void eat(){
		System.out.println("狗吃骨头");
	}
	
	public void shout(){
		System.out.println("汪!汪!汪!");
	}
	
	public void watchDoor(){
		System.out.println("看门");
	}
}
class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
	
	public void shout(){
		System.out.println("喵!喵!喵!");
	}
}

//举例二:
//只要是一个对象都可以调用这个方法
class Order{
	
	public void method(Object obj){
		
	}
}

//举例三:
class Driver{
	
	public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
		//规范的步骤去操作数据
//		conn.method1();//实际调用的是子类中重写的方法
//		conn.method2();
//		conn.method3();
		
	}
	
}


多态性练习:重写方法
package com.atguigu.exer;

//考查多态的笔试题目:
public class InterviewTest1 {

	public static void main(String[] args) {
		Base1 base = new Sub1();
		base.add(1, 2, 3);//sub_1,调用的是重写的方法

		Sub1 s = (Sub1)base;//向下转型后就认为这是一个sub1类
		s.add(1,2,3);//sub_2,向下转型后确定的参数类型优先调用
	}
}

class Base1 {
	public void add(int a, int... arr) {
		System.out.println("base1");
	}
}

class Sub1 extends Base1 {

	//这个方法才是父类方法的重写,下面那个并不是
	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) {
		System.out.println("sub_2");
	}

}

向下转型

目的是为了调用子类中特有的属性和方法

功能少的不可能转化为功能多的,new的父类对象不能强转为子类对象

创建子类时会加载所有的父类,转型只能转为已经加载了的类,因为对象obj本质是woman类,加载woman类时就已经加载了person、object类

同一个父类的各个子类之间不可以互相转换

		//练习:
		//问题一:编译时通过,运行时不通过
		//举例一:
//		Person p3 = new Woman();
//		Man m3 = (Man)p3;
		//举例二:
//		Person p4 = new Person();
//		Man m4 = (Man)p4;

		
		//问题二:编译通过,运行时也通过
//		Object obj = new Woman();
//		Person p = (Person)obj;
		
		//问题三:编译不通过
//		Man m5 = new Woman();
		
		//string和Date没有关系
//		String str = new Date();
		
		//编译时通过,运行时过不了
//		Object o = new Date();
//		String str1 = (String)o;

object类的使用

clone()方法的返回值类型是object,在复制的时候需要考虑是否需要强转为所需要的类型,克隆的对象和前对象的地址不同

finalize方法:在垃圾回收器之前会自动调用的一个方法

getClass():获取当前对象的类

==与equals()

一、回顾 == 的使用:

  • == :运算符
    1. 可以使用在基本数据类型变量和引用数据类型变量中
    1. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
  • 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
  • 补充: == 符号使用时,必须保证符号左右两边的变量类型一致。
  • 二、equals()方法的使用:
    1. 是一个方法,而非运算符
    1. 只能适用于引用数据类型
    1. Object类中equals()的定义:
  • public boolean equals(Object obj) {
    return (this == obj);
    }
  • 说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
    1. 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
    1. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们就需要对Object类中的equals()进行重写.
  • 重写的原则:比较两个对象的实体内容是否相同.

equals()方法重写思路:
1、先判断地址是否相等
2、判断是否是需要判断的类
若是的话,先进行强转,接着再比较各个属性值是否相等

开发中可以自动生成

单元测试方法

  • Java中的JUnit单元测试
  • 步骤:
  • 1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
  • 2.创建Java类,进行单元测试。
  • 此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器
  • 3.此类中声明单元测试方法。
  • 此时的单元测试方法:方法的权限是public,没有返回值,没有形参
  • 4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test;
  • 5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。
  • 6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
  • (详细的步骤如上,也可以直接在符合要求的类里面写上@Test和要测试的类,报错的时候直接点击解决办法就会一步到位解决了)
  • 说明:
  • 1.如果执行结果没有任何异常:绿条
  • 2.如果执行结果出现异常:红条

Junit不用new对象就能用属性了
在Junit里面可以选中不同的方法单独进行测试
在实际开发当中可以写完一个功能就在测试类里面写一个测试方法
注意:自己在造类的时候避免使用Test名字

包装类

基本数据类型——包装类

注意在使用new Integer()时候,括号里面可以放整数,也可以放字符串,但是字符串只能全是数字,不然会报错

			int num1 = 10;
//		System.out.println(num1.toString());
		Integer in1 = new Integer(num1);
		System.out.println(in1.toString());
		
		Integer in2 = new Integer("123");
		System.out.println(in2.toString());
		
		//报异常
//		Integer in3 = new Integer("123abc");
//		System.out.println(in3.toString());

对于布尔型
只要是true,不管大小写,都输出true,其他的输出false

		Boolean b1 = new Boolean(true);//()里面可以直接放true,也可以放string类型的
		Boolean b2 = new Boolean("TrUe");//输出true
		System.out.println(b2);
		Boolean b3 = new Boolean("true123");
		System.out.println(b3);//false

布尔类型的包装类的默认值是null

基本数据类型只需要记住以下转换就可以
自动拆箱与自动装箱

	/*
	 * JDK 5.0 新特性:自动装箱 与自动拆箱
	 */
	@Test
	public void test3(){
//		int num1 = 10;
//		//基本数据类型-->包装类的对象
//		method(num1);
		
		//自动装箱:基本数据类型 --->包装类
		int num2 = 10;
		Integer in1 = num2;//自动装箱
		
		boolean b1 = true;
		Boolean b2 = b1;//自动装箱
		
		//自动拆箱:包装类--->基本数据类型
		System.out.println(in1.toString());
		
		int num3 = in1;//自动拆箱
		
	}
	
	public void method(Object obj){
		System.out.println(obj);
	}
	
	
基本数据类型、包装类——string类

记住以下两种方法就ok,各个方法之间的效率差别不大
前两者转换为string类:valueOf(3.4f)
string类转换为前两者:parseXxx(string)

面试题

	@Test
	public void test3() {
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		System.out.println(i == j);//false
		
		//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
		//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
		//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
		
		Integer m = 1;
		Integer n = 1;
		System.out.println(m == n);//true

		Integer x = 128;//相当于new了一个Integer对象
		Integer y = 128;//相当于new了一个Integer对象
		System.out.println(x == y);//false
	}

和String的常量池一样,基本数据类型也有常量池,取值是-128到127,所以引用的话地址相同,但是超过这个范围则是在堆里new一个了,另外浮点型不在常量池中

创建抽象类的匿名子类对象

在这里插入图片描述

package com.atguigu.java;
/*
 * abstract关键字的使用
 * 1.abstract:抽象的
 * 2.abstract可以用来修饰的结构:类、方法
 * 
 * 3. abstract修饰类:抽象类
 * 		> 此类不能实例化
 *      > 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
 *      > 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
 * 
 * 
 * 4. abstract修饰方法:抽象方法
 * 		> 抽象方法只有方法的声明,没有方法体
 * 		> 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
 *      > 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
 *        若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
 */
public class AbstractTest {
	public static void main(String[] args) {
		
		//一旦Person类抽象了,就不可实例化
//		Person p1 = new Person();
//		p1.eat();
		
	}
}

abstract class Creature{
	public abstract void breath();
}

abstract class Person extends Creature{
	String name;
	int age;
	
	public Person(){
		
	}
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	//不是抽象方法:
//	public void eat(){
//		
//	}
	//抽象方法
	public abstract void eat();
	
	public void walk(){
		System.out.println("人走路");
	}
	
	
}


class Student extends Person{
	
	public Student(String name,int age){
		super(name,age);
	}
	public Student(){
	}
	
	public void eat(){
		System.out.println("学生多吃有营养的食物");
	}

	@Override
	public void breath() {
		System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
	}
}
package com.atguigu.java;
/*
 * 抽象类的匿名子类
 * 
 */
public class PersonTest {
	
	public static void main(String[] args) {
		
		method(new Student());//匿名对象
		
		Worker worker = new Worker();
		method1(worker);//非匿名的类非匿名的对象
		
		method1(new Worker());//非匿名的类匿名的对象	
		System.out.println("********************");	
		
		//创建了一匿名子类的对象:p
		//这个子类没有什么实际含义,就是想用里面的抽象方法,
		//所以就不显式定义子类了,是一种简化的写法
		/*
		 * 类person为抽象类,正常抽象类是无法实例化的,
		 * 但如下用法相当于给person创建了一个临时子类,
		 * 并声明出person类中的方法此时相当于给Person类创建了一个匿名子类,
		 * 子类的实例化对象叫做p
		 */
		Person p = new Person(){

			@Override
			public void eat() {
				System.out.println("吃东西");
			}

			@Override
			public void breath() {
				System.out.println("好好呼吸");
			}


			
		};
		
		method1(p);
		System.out.println("********************");
		
		//创建匿名子类的匿名对象
		method1(new Person(){
			@Override
			public void eat() {
				System.out.println("吃好吃东西");
			}

			@Override
			public void breath() {
				System.out.println("好好呼吸新鲜空气");
			}
		});
	}
	
	
	public static void method1(Person p){
		p.eat();
		p.breath();
	}
	
	public static void method(Student s){
		
	}
}

class Worker extends Person{

	@Override
	public void eat() {
	}

	@Override
	public void breath() {
	}
	
}

创建接口匿名实现类的对象

匿名类就是把定义拉到函数内,匿名对象就是直接new不创建引用

package com.atguigu.java1;
/*
 * 接口的使用
 * 1.接口使用上也满足多态性
 * 2.接口,实际上就是定义了一种规范
 * 3.开发中,体会面向接口编程!
 * 
 */
public class USBTest {
	public static void main(String[] args) {
		
		Computer com = new Computer();
		//1.创建了接口的非匿名实现类的非匿名对象
		Flash flash = new Flash();
		com.transferData(flash);
		
		//2. 创建了接口的非匿名实现类的匿名对象
		com.transferData(new Printer());
		
		//3. 创建了接口的匿名实现类的非匿名对象
		USB phone = new USB(){

			@Override
			public void start() {
				System.out.println("手机开始工作");
			}

			@Override
			public void stop() {
				System.out.println("手机结束工作");
			}
			
		};
		com.transferData(phone);
		
		
		//4. 创建了接口的匿名实现类的匿名对象
		
		com.transferData(new USB(){
			@Override
			public void start() {
				System.out.println("mp3开始工作");
			}

			@Override
			public void stop() {
				System.out.println("mp3结束工作");
			}
		});
	}
}

class Computer{
	
	public void transferData(USB usb){//USB usb = new Flash();
		usb.start();
		
		System.out.println("具体传输数据的细节");
		
		usb.stop();
	}
	
	
}

interface USB{
	//常量:定义了长、宽、最大最小的传输速度等
	
	void start();
	
	void stop();
	
}

class Flash implements USB{

	@Override
	public void start() {
		System.out.println("U盘开启工作");
	}

	@Override
	public void stop() {
		System.out.println("U盘结束工作");
	}
	
}

class Printer implements USB{
	@Override
	public void start() {
		System.out.println("打印机开启工作");
	}

	@Override
	public void stop() {
		System.out.println("打印机结束工作");
	}
	
}


高级编程部分

多线程

有共享数据才会出现线程安全的问题
sleep函数会增加出现线程安全问题的概率
sleep不会释放锁
wait执行会释放锁
notify是把阻塞的线程唤醒,wait才是释放锁
异步并行,同步串行

p455
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果在name的地方又重新new了string类型的话又要在堆空间重新创建两个空间,此时的==比较结果应该是false

集合

set相关面试题
package com.atguigu.exer;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

/**
 * @author shkstart
 * @create 2019 上午 9:36
 */
public class CollectionTest {
    @Test
    public void test1(){
        Collection coll = new ArrayList();

        coll.add(123);
        coll.add(456);
        coll.add(343);
        coll.add(343);

        coll.forEach(System.out::println);
    }


    //练习:在List内去除重复数字值,要求尽量简单
    public static List duplicateList(List list) {
        HashSet set = new HashSet();
        set.addAll(list);
        return new ArrayList(set);
    }
    @Test
    public void test2(){
        List list = new ArrayList();
        list.add(new Integer(1));
        list.add(new Integer(2));
        list.add(new Integer(2));
        list.add(new Integer(4));
        list.add(new Integer(4));
        List list2 = duplicateList(list);
        for (Object integer : list2) {
            System.out.println(integer);
        }
    }

    @Test
    public void test3(){
        HashSet set = new HashSet();
        Person p1 = new Person(1001,"AA");
        Person p2 = new Person(1002,"BB");

        set.add(p1);
        set.add(p2);
        System.out.println(set);

        p1.name = "CC";
        set.remove(p1);
        System.out.println(set);
        set.add(new Person(1001,"CC"));
        System.out.println(set);
        set.add(new Person(1001,"AA"));
        System.out.println(set);

    }


}

在这里插入图片描述
在这里插入图片描述
存储的时候才会按照属性的hash值去存,后来要是属性改了,当前hash值不会改,但是调用remove方法的hash值会是是新的属性对应的hash值,那么有大概率找不到原来的位置,所以就没办法remove掉p1,p1放的位置是根据原始的p1的哈希值算出来进行放置的,而后续加的(1001,CC)算出来的哈希值和刚开始的p1算出来的不一样,因此会放在新的位置。第四个加进去的时候会触发equals函数,一个是AA,一个是CC,所以内容不一样,以链表的形式进行存储。

remove方法是比较的哈希值

反射

最常用的是第三种方法,第一种在编译的时候就必须得确认是哪种类型的对象,第三种在运行的时候才去确定是哪种对象
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值