&逻辑与
|逻辑或
!逻辑非
^逻辑异或(两个条件不一样为真)
&&短路与
||短路或
- 结果相同
- &无论如何右边参与计算
- &&如果左边为假那么右边不参与计算
- ||如果左边为真那么右边不参与计算
左移 m << n 即为 m * 2^n
右移 m >> n 即为 m * 2^-n(保留整数部分)
无符号右移 m >>> n m * 2^-n(m为正数)
&运算(同位与运算)
|运算(同位或运算)
^运算(同位异或运算)
~反码(0变1,1变0)
System.out.println(-31 >> 2);//-8
System.out.println(5 >> 2); // 1
System.out.println(-5 >> 2); // -2
System.out.println(1 << 30);
System.out.println(1024*1024*1024);// 2^30
System.out.println(1 << 31);
System.out.println(1024*1024*1024*2);// -2^31
System.out.println(1 << 32);// 1
System.out.println(1 << 33);// 2, 1<<1
System.out.println(1024*1024*1024*2 << 32); // -2^31
System.out.println(1024*1024*1024*2); // -2^31
System.out.println(1024*1024*1024 << 33); // -2^31
System.out.println(1024*1024*1024*2 >> 32);//-2^31
System.out.println(1024*1024*1024*2 >> 33);//-2^30
(条件表达式) ? 表达式1 : 表达式2
//条件表达式为true运算表达式1
//条件表达式为false运算表达式2
int i = 0, k = 1;
System.out.println(i > k ? i : k);//获取两数中较大数
int i = 1, k = 1, m = 2;
System.out.println((i>k ? i : k) > m ? (i>k ? i : k) : m);//获取三数中较大数
System.out.println(i > k ? (i > m ? i : m) : (k > m ? k : m));//第二种写法
// 也可以使用Math.max函数
System.out.println(Math.max((Math.max(i, j)), k));
if () {
}
if () {
} else {
}
if () {
} else if () {
} else {
}
int i = 2;
switch (i) {
case 1 :
break;
case 2 :
break;
default:
break;
}
String str = "a";
switch (str) {
case "a":
System.out.println("aaa");
// break;
case "b":
System.out.println("bbb");
// break;
default:
System.out.println("nnn");
// break;
//输出:
//aaa
//bbb
//nnn
- for
- while
- do/while
for(int i = 0; i < 5; i++){
System.out.println(i);
}
//输出1-100
int i = 1;
while(i <= 100){
System.out.println(i);
i++;
}
int i = 1;
do{
System.out.println(i);
i++;
}while(i <= 100);
- 执行顺序不一样:
- while是先判断条件-执行-判断条件-执行...
- do-while是执行-判断条件-执行-判断条件-执行...
- 也就是说do-while无论如何会先执行一次
for(;;){
System.out.println("循环中...");
}
while(true){
System.out.println("循环中...");
}
//打印99乘法表
for(int i = 1; i <= 9; i++){
for(int j = 1; j <= i; j++){
System.out.print(i + "x" + j + "=" + (i * j) + " ");//不换行
}
System.out.println();//换行
}
int res = 0;
for(int i = 2; i <= 100; i++){
res = 0;
for(int j = 2; j < i; j++){
if(i % j == 0){
res = 1;
break;
}
}
if(res == 0){
System.out.println(i);
}
}
int a[];
int[] a;
double b[];
Mydate[] c;
int[] ii = new int[4];//声明一个能放4个int类型的数组
int[] ii0 = new int[]{1,2,3,4};//声明一个存放了1,2,3,4四个值的数组
- 一维数组new对象时必须要初始化,以下写法报错
int[] is = new int[];
int[][] ii = new int[2][3];//第一维长度为2(存储元素为2),第二维也就是第一维每个元素的长度是3
int[][] ii1 = new int[2][];//第一维长度为2,第二维先不定义
/*
这里的第二维不定义的话就是第二维度为空值,
在代码的其它部分可以赋予第二维度int数组
*/
int[][] ii0 = new int[][]{
{1,2.3},
{2,3,4}
};
int[] x,y[];定义了x是一个一维数组,y是二维数组
//数组复制(和赋值不一样)
int[] arr = new int[]{2,4,7,1,8,9};
int[] copy = new int[arr.length];
for(int i = 0; i < arr.length; i++){
copy[i] = arr[i];
}
//数组反转
int[] arr = new int[]{2,4,7,1,8,9};
int[] temp = new int[arr.length];
//考虑倒着循环arr,正着给temp赋值
for(int i = 0; i < arr.length; i++){
temp[i] = arr[arr.length - i - 1];
}
for(int i = 0; i < temp.length; i++){
System.out.println(temp[i]);
}
- 数组最好不要和泛型一起用,因为java处理泛型有个擦除的过程,将所有的泛型转化成Object,但是数组不允许这样做,会出很多的问题
例如:
public static <T> T[] test3(T[] objs) {
// T[] res = new T[objs.length]; 报错,不能创建泛型数组
T[] res = (T[]) new Object[objs.length];
for (int i = 0; i < objs.length; i++) {
res[i] = objs[i];
}
return res;
}
//冒泡排序
public static int[] test4(int[] arr) {
int len = arr.length;
// i代表这一轮比出第几大的值
for (int i = len - 1; i >= 0; i--) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
- 复杂度:n + (n-1) + (n-2) + ... = O(n^2)
public static void test11() {
int[] is = {1,2,3,4,5,6,7};
for(int j : is) {
System.out.println(j);
}
}
- 指的是数组指向null,再在这个数组里面用下标取值就会出现空指针异常
- 封装
- 继承
- 多态
- 成员变量
- 成员方法(或函数)
- 定义类
- 定义属性
- 定义方法
/**
* 人
* @author le
*
*/
public class Person {
//属性,成员变量,类的成员变量可以先声明不用初始化,因为是有默认值的
String name;//String默认值是null
int age;//int默认值是0
//行为,方法,也叫函数
/**
* 打印姓名
*/
public void showName(){//方法名称驼峰命名法
System.out.println("姓名:" + name);
}
/**
* 获取年龄
* @return
*/
public int getAge(){//如果是个有返回值的方法,那么方法体最后一行一定用return返回相应数据,返回的数据类型与方法定义一致
return age;
}
}
//实例化Person类,也就是创建Person对象
Person person = new Person();//声明一个Person类型的变量,变量名叫person,并且给person赋值,赋的值就是Person的实例
//new Person()就是实例化Person类
person.name = "张三"; //给person对象的name属性赋值
person.showName();
int age = person.getAge();//有返回值的方法,调用之后就会有一个值,这个值就是方法中return的那部分
System.out.println(age);
person.age = 11;//给person对象的age属性赋值
System.out.println(person.getAge());
- private:该属性只能用该类的方法访问
- public:该属性可以被该类以外的方法访问
- 成员变量:写在类里面的变量
- 实例变量:在类实例为对象后才能使用(不用static修饰)
- 类变量:这样的变量不需要类实例化为对象就可以使用,直接就可以通过类名.属性的方式调用(使用static(意思是静态的)修饰)
- 局部变量:写在方法里面的变量
- 形参:方法定义的变量(需要的参数名)
- 方法局部变量:定义在方法内部的变量
- 代码块局部变量
- 成员变量整个类能使用
- 成员变量中的实例变量只有在实例化后才能使用,在堆内存中
- 成员变量有默认的初始化值
- 成员变量的修饰符可以根据需要选择
- 局部变量只能在它所属的方法的范围内可以使用
- 在栈内存中
- 作用范围结束后释放
- 没有默认初始化值(不包括形参)
- 不指定修饰符
方法体语句;
}
//不用把某个对象赋予某个变量
new Student().showInfo();
- 参数类型不同
- 参数个数不同
- 参数属性呢
- 方法签名是由:方法名称 + 参数类型 + 参数个数组成的一个唯一值,这个唯一值就是方法签名,而 JVM(Java 虚拟机)就是通过这个方法签名来决定调用哪个方法的。
- 所以重载只考虑方法+参数,不用考虑返回值,返回值可以相同也可以不同
- 如果只有参数类型不同,JVM是无法辨别调用哪个方法的:例如
public class OverloadExample {
public static void main(String[] args) {
OverloadExample example = new OverloadExample();
example.method("test"); // JVM 应该调用哪个方法?
}
public int method(String name) {
// doSomething
return 666;
}
public String method(String name) {
// doSomething
return "test";
}
}
//顺序不同也构成重载
void show(int a, char b, double c){}
void show(int a, double c, char b){}
//两者构成重载
public void printInfo(String[] args){
//问题:现在可能给方法传递不同的参数
//如果在这种情况下,我们不知道想给方法传递多少个参数
//设置可变个数的形参
for(int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
- 如果传递0个参数接收到的就是一个长度为0的空数组,而不是null。
- public void printInfo1(int i, String... args)是对的
- public void printInfo1(String... args, int i)不对
- public void printInfo1(int... i, String... args)也不对
/**
* 用java特有的方式传递可变个数的参数,这种参数在使用时与数组的使用方式相同
* @param args
*/
public void printInfo1(String... args){
for(int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
Person3 p3 = new Person3();
p3.printInfo1("lisi","23","男");
//也可以直接传递数组
String[] ss = new String[]{"北京市", "13333333333", "13"};
p3.printInfo1(ss);
- 形参:方法声明时的参数
- 实参:方法调用时传递给形参的实际值
- 若果形参是基本数据类型,那么实参(实际的数据)向形参传递参数时就是直接传递值,把实参的值复制给形参。
- 如果形参是对象,那么实参(实际的对象)向形参传递参数时,也是把值给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址。
- 总之是传递在栈内存中的值,对于基本数据类型是它的实际值对于对象就是该对象在堆中的地址
- 包可以有层及结构,用.来连接(例如day06.test,这就是day06包下的test包)
- 包通常用小写单词
- 如果要引用包下的类要用import声明
- 同一个包下的类引用可以不用import声明
- import day06.test.Person Person p = new Person();
- import day06.test.* Person p = new Person();
- day06.test.Person p = new day06.test.Person();
public class Person{
public Person(){}
//默认构造方法(写不写都存在),因为是public class才是public修饰符,如果class修饰符缺省构造器的修饰符也该缺省
}
Person p = new Person();//new Person对象调用的就是public Person(){}
- 在方法内部使用表示这个方法所属对象的引用
- 在构造器内部使用,表示该构造器正在初始化的对象
public class Person7 {
public Person7(int age, String name){
this.age = age;
this.name = name;
}
int age;
String name;
public void setName(String name){
this.name = name;
}
public void setName1(String name){
this.setName(name);//这里也可以不写this,但写了可以增加可读性
}
public void showInfo(){
System.out.println("姓名:" + this.name);//这里也可以不写this,但写了可以增加可读性
}
}
public Person(){
}
public Person(int age){
this.age = age;
}
public Person(String name){
this();//调用Person()
this.name = name;
}
public Person(int age, String name){
this(1);//调用Person(int age)
this.age = age;
this.name = name;
}
- 使用this()必需放在构造器首行
- 实际上禁止构造器自己调用自己