/**
*
* Less is More
*
* syso + alt + / 自动补齐
*
*变量和常量命名规范
*所有变量,方法,类名:见名知意
*类成员变量:首字母小写和驼峰原则:monthSalary
*局部变量:首字母小写和驼峰原则
*常量:大写字母和下划线:MAX_VALUE
*类名:首字母大写和驼峰原则:Man,GoodMan
*方法名:首字母小写和驼峰原则:run(),runRun()
*
*局部变量:方法或语句块内部定义的变量。生命周期是从声明位置开始到方法或语句块执行完毕为止。先声明,后赋值,必须初始化
*成员变量:(也叫实例变量member variable)方法外部,类的内部定义的变量。从属于对象,生命周期伴随对象始终。没有被static修饰。会自动初始化。
*静态变量:(类变量,static bariable)使用static定义。从属于类,生命周期伴随类始终,从类加载到卸载。
*
*浮点数不精确不要用于比较
*
*转义字符 /" /' //
*
*java中true就是true,false就是false不能用01代替
*
*二元运算符的运算规则:(类型不能大转小)
*整数运算:
*1.如果两个操作数有一个为long,则结果也为long。
*2.没有long时,结果为int。即使操作数全为short,byte,结果也是int。
*浮点运算:
*3.如果两个操作数有一个为double,则结果为double。
*4.只有两个操作数都是float,结果才为float。
*取模运算:
*5.“余数”符号和左边操作数相同,如7%-3=1
*
*a*=b+3;//相当于a=a*(b+3);
*
*逻辑运算符:
*逻辑与 & 两个操作数为true,结果才是true
*逻辑或 | 两个操作数有一个是true,结果就是true
*短路与 && 只要有一个为false,则直接返回false
*短路或 || 只要有一个为true,则直接返回true
*逻辑非 ! 取反,!false为true,!true为false
*逻辑异或 ^ 相同为false,不同为true
*
*位运算符:
*~ 取反,只对一个数字运算
*& 按位与运算
*| 按位或运算
*^ 按位异或运算
*<< 左移运算符,左移一位相当于乘2 1<<1=2
*>> 右移运算符,右移一位相当于除2
*
*字符串连接符:
*'+'号左右只要有一个为字符串,就变为字符串连接符
*
*条件运算符(三目运算符)
*x>y?a:b
*
*运算符的优先级:
*不需要刻意记这些优先级,表达式里面优先使用小括号来组织
*逻辑与、逻辑或、逻辑非的优先级一定要熟悉!(逻辑非>逻辑与>逻辑或)。
*如:a||b&&c的运算结果是:a||(b&&c),而不是(a||b)&&c
*
*自动类型转换:
*大转小强制转,小转大自动转,
*特例:
*short b = 12; //合法,因为12(int型),没有超出short的表数范围
*short b = 1234567; //非法,因为1234567超出了short的表数范围
*long e =3.23; //非法,小数默认double类型,比long大不能自动转换,float也不行
*
*三大结构:
*顺序结构、选择结构、循环结构
*
*switch碰到break才结束
*
*带标签的continue和break
*
*方法:
*实参的数目、数据类型和次序必须和所调用的方法声明的形式参数列表匹配
*return语句终止方法的运行并指定要返回的数据
*Java中进行方法调用中传递参数时,遵循值传递的原则(传递的都是数据的副本)
*基本类型传递的是该数据值的copy值
*引用类型传递的是该对象引用的copy值,但指向的是同一个对象
*
*方法重载(overloa):
*重载的方法实际是完全不同的方法,只不过名称相同而已
*方法名相同,参数个数不同,构成重载
*方法名相同,参数类型不同,构成重载
*方法名相同,参数顺序不同,构成重载(double a, int b)和(int b, double a)
*只有返回值不同,不构成重载
*只有参数名称不同,不构成重载
*
*递归:
*递归结构包括两个部分,递归头和递归体
*递归既耗时间,又耗内存
*
*类:
*类里面有属性和方法,只有属性没有方法叫做结构体
*
*Java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area
*栈的特点如下:
*1.栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
*2.JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数,局部变量等)
*3.栈属于线程私有,不能实现线程间的共享
*4.栈的存储特性是“先进先出,后进后出”
*5.栈是由系统自动分配,速度快,栈是一个连续的内存空间
*堆的特点如下:
*1.堆用于存储创建好的对象和数组(数组也是对象)
*2.JVM只有一个堆,被所有线程共享
*3.堆是一个不连续的空间,分配灵活,速度慢
*方法区(又叫静态区)特点如下:
*1.JVM只有一个方法区,被所有线程共享!
*2.方法区实际也是堆,只是用于存储类、常量相关的信息
*3.用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
*
*构造器:
*构造器也叫构造方法(constructor),用于对象的初始化
*要点:
*1.通过new关键字调用!!
*2.构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能再构造器里使用return返回某个值
*3.如果我们没有定义构造器,则编译器会自动定义一个无参的构造器。如果已定义则编译器不会自动添加!
*4.构造器的方法名必须和类名一致!
*构造方法的第一句总是super(),不管调不调用
*
*垃圾回收机制(Garbage Collection)
*C++中没有垃圾回收器
*垃圾回收过程:
*任何一种垃圾回收算法一般要做两件基本事情:
*1.发现无用的对象
*2.回收无用对象占用的内存空间
*垃圾回收机制保证可以将“无用的对象”进行回收。无用的对象指的是没有任何变量引用该对象。Java的垃圾回收器通过相关算法发现无用的对象,并进行清除和整理
*①引用计数法:
*堆中每个对象都有一个引用计数,被引用一次,计数+1,被引用变量值变为null,则计数-1,直到计数为0,则表示变成无用对象。优点是算法简单,缺点是“循环引用的无用对象”无法识别
*②引用可达法(根搜索算法)
*程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的y引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕以后,剩余的节点则被认为是没有被引用到的节点,即无用的节点
*
*通用的分代拉吉回收机制:
*分代垃圾回收机制,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。我们将对象分为三种状态:年轻代、年老代、持久代。JVM将堆内存划分为Eden、Survivor(这两个都是年轻代)和Tenured/Old(年老代)空间,持久代在方法区
*1.年轻代:
*所有新生成的对象首先都是放在Eden区,年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC,每次Minor GC会清理年轻代的内存,算法采用效率较高的复制算法,频繁的操作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域
*2.年老代:
*在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代对象越来越多,我们就需要启动Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域
*3.持久代:
*用于存放静态文件,如Java类,方法等,持久代对垃圾回收没有显著影响
*Minor GC:
*用于清理年轻代区域,Eden区满了就会触发一次Minor GC,清理无用对象,将有用对象复制到Survivor1、Survivor2区中(这两个区,大小空间也相同,同一时刻Survivor1和Survivor2只有一个在用,一个为空)
*Major GC:
*用于清理老年代区域
*Full GC:
*用于清理年轻代,年老代区域,成本较高,会对系统性能产生影响
*垃圾回收过程:
*1.新创建的对象,绝大多数都会存储在Eden中
*2.当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区
*3.当Eden区再次满了,会将S1中的不能清空的对象存到另一个Survivor中,如S2,同时将Eden区中的不能清空的对象,也复制到S1中,保证Eden和S1,均被清空
*4.重复多次(默认15)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)中
*5.当Old区满了,则会触发一个一次完整地垃圾回收(FullGC),之前新生代的垃圾回收称为(MinorGC)
*JVM调优和Full GC:
*在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节,有如下原因可能导致Full GC:
*1.年老代(Tenured)被写满
*2.持久代(Perm)被写满
*3.System.gc()被显式调用(程序建议GC启动,不是直接调用GC,还是由垃圾回收机制说的算)
*4.上一次GC之后Heap的各域分配策略动态变化
*
*创建一个对象分为如下四步:
*1.分配对象空间,并将对象成员变量初始化为0或空
*2.执行属性值的显示初始化
*3.执行构造方法
*4.返回对象的地址给相关的变量
*this的本质就是“创建好的对象的地址”由于在构造方法调用前,对象已经创建,因此,在构造方法中也可以使用this代表“当前对象”
*构造器的调用必须位于第一句!!!!(当一个构造器调用另一个构造器时)
*this最常用的方法:
*1.在程序中产生二义性之处,应使用this来指明当前对象:普通方法中,this总是指向调用该方法的对象,构造方法中,this总是指向正要初始化的对象。
*2.使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中使用,并且必须位于构造方法的第一句
*3.this不能用于static方法中
*
*static关键字:
*在类中,用static声明的成员变量为静态成员变量,也成为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效
*static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象
*
*静态初始化块:
*构造方法用于对象的初始化,静态初始化块用于类的初始化操作,在静态初始化块中不能直接来访问非static成员
*注意事项:
*静态初始化块执行顺序(学完继承在看这里)
*1.上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止
*2.构造方法执行顺序和上面顺序一样
*先加载类,再执行构造
*
*参数传值机制:
*Java中,方法中所有参数都是“值传递”,也就是“传递的是值的副本”,也就是说,我们得到的是“原参数的复印件,而不是原件”。因此,复印件改变不会影响原件
*·基本数据类型参数的传值:
*传递的是值的副本。副本改变不会影响原件
*·引用类型参数的传值:
*传递的是值的副本。但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值”,也意味着原参数指向对象的值也发生了改变
*
*包机制是Java中管理类的重要手段,开发中,我们会遇到大量同名的类,通过包我们很容易解决ll类重名的问题,也可以实现对类的有效管理。包对于类,相当于文件夹对文件的作用
*我们通过package实现对类的管理,package的使用有两个要点:
*1.通常是类的第一句非注释性语句
*2.包名:域名倒着写即可,再加上模块名,便于内部管理类
*注意事项:
*1.写项目时都要加包,不要使用默认包
*2.com.gao和com.gao.car,这两个包没有包含关系,是两个完全独立的包,只是逻辑上看起来后者是前者的一部分。
*
*JDK中的主要包
*java.lang 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能
*java.awt 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)
*java.net 包含执行与网络相关的操作的类
*java.io 包含能提供多种输入/输出功能的类
*java.util 包含一些实用工具类,如定义系统特性,使用与日期日历相关的函数
*
*使用不同包中的类:
*1.在类名前添加包名 如:cn.sxt.oo.User user = new cn.sxt.oo.User();
*2.导入类,import cn.sxt.oo.User;//表示导入了User类,也可以import cn.sxt.oo.*;//导入oo下面的所有类,但是会降低编译速度(*是通用符),但是可能会出现重名情况
*静态导入:
*静态导入(static import)是JDK1.5新增加的功能,其作用是用于导入指定类的静态属性,这样我们可以直接使用静态属性。import static java.lang.Math.*;//导入Math类中所有的静态属性
*
*继承使用要点:
*1.父类也称作超类,基类,派生类等。
*2.Java中只有单继承,没有像C++那样的多继承,多继承会引起混乱,使得继承链过于复杂,系统难于维护
*3.Java中没有多继承,接口有多继承
*4.子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)
*5.如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object (Object是所有东西的父类) Ctrl+T 可以查看类的继承结构
*
*instenceof运算符:
*instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建的对象时,返回true;否则,返回false 如:System.out.p[rintlen(stu instanceof Student);还可以 System.out.printlen(new Person() instanceof Student);
*
*方法的重写override:
*子类通过重写父类的方法,可以用自身的行为替换父类的行为。
*方法的重写需要符合下面的三个要点:
*1."==":方法名,形参列表相同
*2."<=":返回值类型和声名异常类型,子类小于等于父类
*3.">=":访问权限,子类大于等于父类
*
*Objec类:
*Object类是所有Java类的根基类,也就意味着所有的Java对象都拥有Object类的属性和方法
*按住 Ctrl 可以查看源码
*
*
*/
import java.math.*;
import java.util.Scanner; //输入流
import java.util.concurrent.SynchronousQueue;
public class TestData {
int a; //成员变量
static int size; //静态变量
public static void main(String[] args) {
int age = 18; //局部变量
BigDecimal bd = BigDecimal.valueOf(1.0);
bd = bd.subtract(BigDecimal.valueOf(0.1));
bd = bd.subtract(BigDecimal.valueOf(0.1));
System.out.print(bd);
int a = 3;
System.out.println("\n");
System.out.println(a==3);
System.out.println(a!=3);
System.out.println(a>3|a==3);
boolean b1 = true;
boolean b2 = false;
System.out.println("\n\n");
System.out.println(b1&b2);
System.out.println(b1|b2);
System.out.println(b1^b2);
System.out.println(!b2);
boolean b3 = 1>2&&2<(3/0);
// boolean b3 = 1>2&2<(3/0); //不是短路与会报错,因为会接着计算&后面的值
System.out.println(b3);
System.out.println(1<<1);
System.out.println(3+4); //加号
System.out.println(3+"4"); //字符串连接符
System.out.println(3+'4'); //assic?????
String testa = "3";
int testb = 4;
int testc = 5;
System.out.println(testa+testb+testc); //括号里是从左至右算,a+b=34,再+c=345,字符串连接符
System.out.println(testb+testc+testa); //b+c=9,9+a才变为字符串连接符
int score = 80;
String type = score<60?"不及格":"及格"; //三目运算符
System.out.println(type);
int money = 1000000000; //10亿
int years = 20;
//返回的total是负数,超出了int的范围
int total = money*years;
System.out.println("total="+total);
//返回的total仍是负数,默认是int,因此结果会转换成int值,再转成long。但是已经发生了数据丢失
long total1 = money*years;
System.out.println("total="+total1);
//正确,因为将一个因子变成long,整个表达式发生提升。全部用long来计算
long total2 = money*((long)years);
System.out.println("total2="+total2);
Scanner scanner = new Scanner(System.in);
System.out.println("请输入名字:");
// String name = scanner.nextLine();
System.out.println("请输入你的爱好");
// String favor = scanner.nextLine();
System.out.println("请输入你的年龄");
// int age1 = scanner.nextInt();
System.out.println("##############");
// System.out.println(name);
// System.out.println(favor);
// System.out.println(age1);
double ran = Math.random(); //返回0-1的一个随机数,不包括1[0.1),左闭右开
/* while(true){
System.out.println(ran);
}*/
outer:for (int i = 101; i < 150; i++) {
for (int j = 2; j < i / 2; j++) {
if (i % j ==0){
continue outer;
}
}
System.out.println(i + " ");
}
//递归阶乘算法
int testx = scanner.nextInt();
long factorial1 = System.currentTimeMillis(); //返回当前时刻(毫秒数)
System.out.println(factorial(testx));
long factorial2 = System.currentTimeMillis();
System.out.println("耗时(ms):"+(factorial2 - factorial1)); //‘+’这里是字符串拼接
}
//递归阶乘方法
static long factorial (int n){
if (n == 1){
return 1;
}else {
return n * factorial(n - 1);
}
}
}