用了java从入门到精通和Java核心技术的基础篇,准备第一本为主,第二本为辅,实践加上理论的去学习。
java是用类组成的。每个类都要有一个主函数。含有main方法的类称为Java主类。
这个是声明在主函数外面的
这个是申明在主函数里面的。
里面的变量定义可以边定义边操作:long s1 = s2+s3+s4;
final <类型> <变量名>=<值>
在Java中,变量名和变量名所对应的数据是存放在不同的地方的。
一般申明在主函数外部,这个可以参考C语言。
System.out.println(s1);
这个就是输出的语法。这里有个问题,能不能一次性输出一大堆。
打印的时候可以类似于python里面,用+这个符号,这个跟C语言有点不大一样。
注意,整数类型不能以0开头,八进制以0开头,十六进制以0X开头。
整数类型的名称是和他们能表示的进制位有关系,byte是八位,依次成倍数增长。可以表示从负数到正数。
char x='<字符>'
这个就是单个字符的申明。多个字符用双引号。package cd.idcast.num;
public class test {
public static void main(String[] args) {
int s1=15;
System.out.println((char)s1)
}
}
就是将目标类型用圆括号括起来,然后跟上变量。
目前没搞懂,为什么main里面要有一个String[] args
以及stactic是什么意思?是全局变量的意思吗?
final <类型> <变量>
在整个类中都适用的变量叫做成员变量。成员变量中包含两种变量:
static <数据类型> <变量>
<类名>.<静态变量>
来访问。只在当前的类里面有效,一旦跳出了这个类,就无效了。
这里面最重要的就是自增和自减,这个参考C语言。
这个和其他语言是一样的,参考python和c语言。
这个就是:
这个比较的关键,因为,这个可以减少空间复杂度。
boolean b = 20<45?true:false
上面这个例子只是一部分,当然我们可以定义其他类型来完成三元运算。
即满足条件就是true的部分,否则就是false的部分。
从低级类型向高级类型的转换,这个是由系统自动执行的,不需要我们人为的来完成。
这里就有一个转换表:
当我们把高精度的数据赋给低精度的数据的时候,我们就要用显示类型转换了。这个和C语言是不一样的。
这个和上面那个刚好是相反的。
(<类型>)<变量>
这个和C语言一样
这个就是/** */
中间的被视为文档注释。
这个就是在函数总又加了一对大括号,在大括号里面会新开辟一个命名空间,一旦这里面的变量到了外面使用,就会报错。
这里面就是if语句了,这个是语言中非常重要的环节之一。这个和C语言很像。
switch也是一样的。
for语句和循环语句,以及do while语句,这个和C语言是一样的,我们沿用就行了。
其中有一个foreach语句,这个是for语句的精髓。
int arr[]={1,8,9}
for(int x:arr){
System.Out.printIn(x)
}
这个变量的定义要和数组中的保持一致。
java中有标签语法,就是说内层循环可以直接结束外层循环,当指定标签的时候。
Loop:for(int i = 0;i<=10;i++){
for(int j = 0;j<=5;j++){
if(j==3){
break Loop;
}
}
}
类似于这样,就可以结束外层的循环嵌套。
这个我看上去和python有点像,又和C语言有点像。
这个是基于序列之上的。
char a[]={'g','o','o','d'};
String s = new String(a,<>,<>);//第一个参数是起始坐标,第二个参数是取的的个数。
//或者直接这么定义
String s = new String("student");
String是字符串的意思,然而,char是字符的意思。
或者直接定义String <变量>;
直接用加号。
str.length();
str指的就是字符串。
indexOf;
查找字符串第一次出现的位置
lastIndexOf;
查找字符串最后出现的位置
str.charAt(<坐标>);
str.substring(int x);
这个就是从指定的字符串索引开始往后截取。当然,也可以定义结束的位置。取头不取尾。
str.trim();
这个因为是类写的,所以有多态。
str.replace(
str.startsWith(<期望字符>);
str.endsWith(<期望字符>);
这两个方法返回的都是布尔值。
str.equals(
下面这个方法是忽略大小写。
str.equalsIngnoreCase(
判断两个字符的前后位置
str.CampareTo(<另一个字符>)
转换大小写
str.toLowerCase()
str.toUpperCase()
这个比较的管用,在处理字符串方面用的很多,至少爬虫这方面我是深有体会:
str.split(<要分割的字符串>)
同时,加个逗号后面跟整型,可以标识分割几次。
这个等用到的时候再说,练起来没有多大的意义。
但是常规个字符格式化是要记住一些的。这个就跟C和python中的格式化输出一个道理。
这个就跟内存有关系了,在python中我们避免一直用str += str
的原因就是,这样会不停的创建出一个新的内存,时间复杂度很高。Java中有类似的机制避免这种情况。
Java中提供了一种字符串生成器来减少系统的开销。
这个我觉得它应该是使用了一种花销平坦的机制,和python的列表是很像的。
StringBuilder <变量> = new StringBuilder("");
不过,这里建议使用变量名是builder,这个可能是一个规定。
str.toString();
str.insert(int start,int end);
这样就可以在字符串中插入
str.delete(int start ,int end);
数组有一维的和二维的等等。在Java中,我们每一个都是一个对象,所以我们在申明了数组的变量之后,还要new一个对象,这样的话,系统才会给它分配内存,不然这个变量名就是无效的,下面举一个例子,我们来创建一个一维的int类型的数组。
int x[];
x = new int[6];
现在才算真正的创建了一个一维的数据,长度是6。
当然,上面的语法是可以合起来的:int <变量名>[]=new int[6]
int <>[]={<元素>,...,<元素>};
int <>[]=new int[]{<元素>,...,<元素>};
这个也是可以的。
数组的访问跟python的一摸一样,就是用下标的方式进行访问,这里我觉得可以用none乘以任意值来初始化数据,当然,这个是我的猜想。
这个初始化和一维是一样的,只不过,我们还要不停的为两个维度的数组分配内存
int a[][]=new int[2][4];
a[0]=new int[5];
a[1]=new int[2];
int a[][]={{<元素>},...,{<元素>}}
这个初始化和C语言是一样的。
这个参考当时的C语言。
这里采用的是拆解遍历法
for(int xi[]:xx){
int j=0;
for(int e:xi){
if (i==1&&j==2){
System.out.println(e);
break;
}else {
System.out.println(e);
j++;
}
}
i++;
}
里面用的就是java中的foreach语句。
第一个循环是不停的把二维变成一维;第二个循环就是把一维变成一个个的元素。这个循环就是在不停的把数据降维度输出。每次都下一个维度。
我们可以用print这个函数来让它在同一行输出。
我们可以使用fill方法来对数据进行填充。举个例子来讲:
<>.fill(<类型> <数组>[],<填充的东西>)
这个只是一个例子,这个fill可以用一个值填充整个数据。
package cd.idcast;
import java.lang.reflect.Array;
import java.util.Arrays;
public class 数组的填充 {
public static void main(String[] args) {
int arry[]=new int[8];
Arrays.fill(arry,5);
for(int i=0;i<arry.length;i++){
System.out.print(arry[i]+", ");
}
}
}
我们发现,填充这个方法,用的是Arrays对象。当然,填充也是可以指定范围的,这个可以类似于替换数组中的元素。
Arrays.fill(<数组变量>,<起始位置>,<结束位置>)
这个就是指定位置的填充,也可以理解为替换。
Arrays.sort(<对象>)
这个就要用到另一个对象了。
copyOf(<数组对象>,<复制的长度>)
copyOfRange()
这个就是指定数组的指定复制范围。
binarySearch(Object[] a,int fromIndex,int toIndex,Object key);
/*其中,a 表示要进行查找的数组,fromIndex 指定范围的开始处索引(包含开始处),toIndex 指定范围的结束处索引(不包含结束处),key 表示要搜索的元素。
在使用 binarySearch() 方法的上述重载形式时,也需要对数组进行排序,以便获取准确的索引值。如果要查找的元素 key 在指定的范围内,则返回搜索键的索引;否则返回 -1 或 “-插入点”。插入点指要将键插入数组的位置,即范围内第一个大于此键的元素索引。*/
思想就是,不停的从头开始对比,但是交换的次数是越来越少的。因为每次交换都能保证最大的一定在最下面。当然,这个是升序,我们当然可以降序排列
package cd.idcast.num;
public class 冒泡排序 {
public static void main(String[] args) {
int[] array = {63,5,24,1,100,3};
//冒泡排序
}
public void sort(int[] array){
for(int i = 1;i<array.length;i++){
for(int j=0;j<array.length-i;j++){
if(array[j]>array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
showArray(array);
}
}
public void showArray(int[] array){
for(int i:array){
System.out.print(">"+i);
}
System.out.println();
}
}
这个就是从最后一个位置开始,每次选出最大的一个,然后和位置交换,这个位置呢,就是array[array.length-i],这个位置每循环一次就会减一。为什么说最开头的这个不换了呢,因为当后面位置的数全是最大的时候,那么第一个数一定是最小的。
package cd.idcast.num;
public class Select_order {
public static void main(String[] args) {
int[] array = {96,52,18,2,1,0};
Select_order sorter = new Select_order();
sorter.sort(array);
}
public void sort(int[] array){
int index;
for(int i=1;i<array.length;i++){
index = 0;
for(int j=1;j<=array.length-i;j++){
if(array[j]>array[index]){
index = j;
}
int temp;
temp = array[array.length-i];
array[array.length-i] = array[index];
array[index] = temp;
}
pprint(array);
}
}
public void pprint(int[] array){
for(int x:array){
System.out.print(x+" ");
}
System.out.println();
}
}
类是封装对象的载体,我们不能把单一的事物称为类。
现在还没有办法理解这个public的具体含义,以及public和private是怎么协同工作的。
我们先要从设计一个类开始,然后再着手的去实现类里面的方法。
我们通常用类名来申明一个对象,同时,要配合上new来让该对象能够不停的被访问:Book one_editor = new Book()
我们引用的类实例都是外部的,是一个具体的,而且,每个不同的变量指向不同的类实例。
我们都会翻译,UML是统一建模语言,是一种可视化的面向对象建模语言,是一种用来对真实世界物理进行建模的标准标记,用图形方式表现典型的面向对象系统的整个结构。它的作用域不局限于支持面向对象的分析与设计,还支持从需求分析开始的软件开发的全过程。
https://blog.csdn.net/xdd19910505/article/details/18698825/
上面的网站中有详细的说明。
不管前面的权限修饰符是public或者是private,这个都是成员方法。成员方法的声明格式是:权限修饰符 返回值类型 方法名(参数类型 参数名){//方法体}
这个我觉得如果用python中的类来理解会好一点。
在Java中,权限修饰符有三个:
如果是public,那么这个就属于公共的,也就是说任意地方都能访问到。
如果是private的话,这个就跟python中类里面,用下划线定义的变量或者是函数,是私有的,它存在在本类当中,但是不能够被外界访问。
如果是protected的话,那就是只有其他包不能访问,同包里面,或者同一个文件里面都是可以访问到的。
在类中,如果学过python,那么我们将this映射成python中的self,也就是实例对象本身。我们将private映射成用“_”开头的私有属性或者函数,也就是只有内部才能调用和访问,子类以及其它是访问不了的。
如果一个类前面没有任何的权限修饰符的话,那么我们将这个类默认成protected类型的类,也就是只有本包和子类可以访问该类。本包外的就不行。
在类中的方法如果不定义权限修饰符,那么会默认是public,因为类的权限设定会影响里面的权限设定。
这个就跟python中的命名空间是一个概念,在该命名空间中,变量的名称是不能够重复的,但是在不同的作用域里面,变量的名称确实是可以重复的。这个就跟在两个for循环里面用同样的变量i是一个道理。
局部变量在调用结束后就会被销毁。
这个就相当于python中的self,而且,这个可以直接作为对象返回。
这个是在项目中创建public <类名称>(){//函数体}
这个可以没有返回值,同时,如果没有参数的话,我们可以在函数体中的第一句加上this("<参数>")
,但也只能是第一句。
这个就是可以让别的类也访问的常量类型,用于节省内存。
用类名加上点来调用方法。
static{
}
我觉得这个跟python中的init就很像。
这个就是前面的权限修饰符。
package cls_test;
public class lei_tes_2 {
public lei_tes_2(){
System.out.println("Hello");
}
public static void main(String[] args) {
new lei_tes_2();
}
}
在这里面,我们发现,在主类里面创建了一个lei_tes_2,它的构造方法和它是同名的。
构造方法就是相当于初始化方法,这个会在主函数中一旦遇到了new之后自动调用,构造函数的方法就是在主函数外面创建一个同名的类名,里面定义其它代码。
前面是比较地址是否相等,后者是字符串的方法,比较两个字符串是否相等。
将对象赋值为null或者用finalize()方法都是可以的。同时我们可以用System.gc()来强制回收对象。
每个类中,只有一个main方法,同时,有很多的不同类,这些类最终会在main方法中被调用。要想创建一个完整的程序,就要将他们结合到一块。
有些情况下,我们需要将数字作为对象进行处理,所以这个时候,我们就需要包装类了。
在这个类里面就有很多的方法:
其中有很多转换的方法在pdf189页,这里举一个例子:
package Pack_class_test;
public class Integ {
public static String[] num = {"45","56","343"};
public static void main(String[] args) {
int sum = 0;
for (String s : num) {
int x = Integer.parseInt(s);
sum += x;
}
System.out.println(sum);
}
}
这个就是将数字当作对象来处理了。
这个就是,如果我创建了一个Boolean的对象,那么如果对象不是true(忽略大小写),那么返回false。
其他方法和上面是类似的。
package Pack_class_test;
public class Integ {
public static String[] num = {"45","56","343"};
public static void main(String[] args) {
int sum = 0;
for (String s : num) {
int x = Integer.parseInt(s);
sum += x;
}
System.out.println(sum);
Boolean bool = Boolean.valueOf("type");
System.out.println(bool);
}
}
其他的方法是类似的,我们只需要查书就行了。
这个相当于python中的format,非常的有用,尤其是在处理一些别的方面的时候。
package Pack_class_test;
import java.text.DecimalFormat;
public class NumFormat {
static public void FormatNum(String pattern,double num){
DecimalFormat myformat = new DecimalFormat(pattern);
String nums = myformat.format(num);
System.out.println(nums);
}
public static void main(String[] args) {
FormatNum("000.00kg",185.6989);
FormatNum("#####.##",15.3);
FormatNum("#.###%",0.236);
}
}
其他的书中也有介绍,用到的时候再具体的查书。在PDF199页这里。
<对象>.setGroupingSize(<整型>)
Sting <变量> = <对象>.format(<整型>)
用到了查书。PDF203页。
这个根据以往用python的经验来讲,还是比较重要的。
这个模块呢,只能产生0-1之间的数,所以我们用这个的时候,需要乘上相应的值来达到任意区间随机数的目的。
package Pack_class_test;
import java.text.DecimalFormat;
public class NumFormat {
static public void FormatNum(String pattern,double num){
DecimalFormat myformat = new DecimalFormat(pattern);
String nums = myformat.format(num);
System.out.println(nums);
}
static public void RandomNum(double num1,double num2){
int s = (int)(num1)+(int)(Math.random()*num2);
System.out.println(s);
}
public static void main(String[] args) {
FormatNum("000.00kg",185.6989);
FormatNum("#####.##",15.3);
FormatNum("#.###%",0.236);
RandomNum(12.6,89.898989);
}
}
我们也可以用它来生成随机的字符,这个和上面的方法是一致的,只不过,我们用的是char类型。
Random r = Random();
后面就可以调用里面的方法了,这个书中都有列出,这里略过,要用的时候查文档就行。书PDF208页。
BigInterger可以表示任意大小的整型。
里面的算术运算是以对象的形式进行的,我们来举几个例子:
package Pack_class_test;
import java.math.BigInteger;
public class bigNum {
public static void main(String[] args) {
BigInteger bigs = new BigInteger("45");
System.out.println(bigs.add(new BigInteger("69")));
}
}
其他的和这个类似。
在这个类中,不同的传参转换的结果是一样的,我们可以传double类型,也可以传string类型。
package Pack_class_test;
import java.math.BigDecimal;
import java.math.BigInteger;
public class bigNum {
public BigDecimal add(double var1,double var2){
BigDecimal d1 = new BigDecimal(Double.toString(var1));
BigDecimal d2 = new BigDecimal(Double.toString(var2));
return d1.add(d2);
}
public static void main(String[] args) {
// System.out.println(bigs.add(new BigInteger("69")));
// BigDecimal dd = new BigDecimal("15.26541");
// System.out.println(dd.add(new BigDecimal("8861.165489461")));
// System.out.println(BigCal);
bigNum b = new bigNum();
System.out.println(b.add(1254.156,896.3486416));
}
}
子类中可以重构父类的方法和参数,但是除了权限修饰符为private的除外,同时,重写时不能降低权限的修饰范围,也就是提升是可以的。
Java中,用extends来表示继承类
class Text2 extends Text1
这里我们发现,是前面的继承了后面的
同时我们用super();来调用父类方法。
super();//这个是调用父类的构造方法。
super.<方法>();
使用父类方法的时候要注意,如果定义的是static类型的函数,那么不用加super,直接调用即可。
实例化的时候,父类先实例化,然后再是子类。
这个是一个基类,我们创建的Java类都默认继承了它。
这个方法是类自动继承的,我们通常重写他,它会在类被实例化之后自动调用。同时,它可以让类对象作为一个字符串输出。
在实例化的过程中,equals是默认"==",所以我们要重写它。
package Pack_class_test;
class Fulei{
public static void draw(Fulei p) {
System.out.println("劳资是你爸爸");
}
}
public class S_B extends Fulei{
public static void main(String[] args) {
S_B p = new S_B();
draw(p);
}
}
也就是子集向全集转化的时候,就可以实现向上转型。
static类型的函数,只初始化一次,所以继承后可以直接调用。
这个时候必须使用显示类型转换,不然就会报错。
<类名> <变量> = (类名)<变量>
这样配合上面的转型,可以让程序变得更加的健壮。
package Pack_class_test;
class QQQ{
public static void draw(QQQ q) {
System.out.println("来了老弟");
}
}
class Square extends QQQ{
public static void gg(){
int i=0;
System.out.println("我是方");
}
}
class Anything{
}
public class Judge_ex extends QQQ{
public static void main(String[] args) {
QQQ p = new QQQ();
if(p instanceof Judge_ex){
System.out.println("没错,现在我要开始转换了");
Judge_ex q = (Judge_ex)p;
}
if(p instanceof Square){
System.out.println("是方的");
Square q = (Square)p;
System.out.println("转型完成");
}
}
}
一个类里面,Java允许有相同名字的不同函数,只要这些函数的类型,传参等等不一样,JAVA就能识别他们,这样方便我们管理代码。
同时,里面有一个任意传参的语法:
<类型>...<变量>
这个就相当于数组了。
package Pack_class_test;
public class ReloadFuc {
public static double add(double...num){
double sum=0;
for(double x:num){
sum +=x;
}
return sum;
}
public static int add(int...num){
int sum = 0;
for (int x:num){
sum +=x;
}
return sum;
}
public static void main(String[] args) {
System.out.println(add(1,5,6,8));
System.out.println(add(1.2,5,8.6,45));
}
}
利用了向上转型的特性,比如说绘制四边形,我们定义一个大类,然后让里面的子类同变成参数传递进draw这个大类里面,然后通过不同的限制来处理不同的四边形绘制,这个大概就是多态的思想。
package Pack_class_test;
public class Duotai {
//四边形类
private final Duotai[] qtest = new Duotai[6];
private int nextindex = 0;
public void draw(Duotai q){
if(nextindex<qtest.length){
qtest[nextindex]=q;
System.out.println(nextindex);
nextindex++;
}
}
public static void main(String[] args) {
Duotai q = new Duotai();
q.draw(new Sq());
q.draw(new Parallelogramgle());
}
}
class Sq extends Duotai{
public Sq(){
System.out.println("我是正方形");
}
}
class Parallelogramgle extends Duotai{
public Parallelogramgle() {
System.out.println("我是长方形");
}
}
这里我们就可以看到,我们在主类方法里面,就实现了多态的运行。
多态和接口的技术相结合,就能让代码变得更加的健壮。
在Java中,是不允许多重继承的,但是呢,如果调用接口就是可以的:
class <类名> implements <接口>,<>...<>{
}
接口之间也是可以继承的。这个继承方法和类是一样的。
interface <> extends <>{}