java
1package calcvm; 2 3import java.io.*; 4import java.util.*; 5 6import com.vaadin.flow.component.button.Button; 7import com.vaadin.flow.component.html.H2; 8import com.vaadin.flow.component.html.Label; 9import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 10import com.vaadin.flow.component.orderedlayout.VerticalLayout; 11import com.vaadin.flow.component.textfield.TextField; 12import com.vaadin.flow.router.PageTitle; 13import com.vaadin.flow.router.Route; 14import com.vaadin.flow.router.RouteAlias; 15 16@PageTitle("Calc VM") 17@Route(value = "calcvm") 18@RouteAlias(value = "") 19 20public class CalcVMView extends VerticalLayout { 21 22 public CalcVMView() { 23 // 中置記法入力 24 TextField infixExpr = new TextField(); 25 infixExpr.setWidth("400px"); 26 Button translateButton = new Button("変換"); 27 Button generateButton = new Button("生成"); 28 Button executeButton = new Button("実行"); 29 30 // 後置記法出力 31 32 33 translateButton.addClickListener(e -> { 34 String str = infixExpr.getValue(); //strに中置記法の式を代入 35 Node tree = new Node(str); 36 37 //二分木に格納する 38 tree.parse(); 39 40 String str2 = tree.getExpression(""); //str2に後置記法の式を代入 41 Label postfixOut = new Label(); 42 postfixOut.setText(str2); 43 String[] data2 = str2.split(","); //カンマ区切りでdata2に格納する 44 45 46 }); 47 48 // スタックマシン命令列 49 VerticalLayout vmInsns = new VerticalLayout(); 50 int lg = str2.length(); 51 String[] strArray = str2.split(""); 52 generateButton.addClickListener(e -> { 53 vmInsns.removeAll(); 54 55 for(String s: strArray) { 56 switch (s) { 57 case "+":vmInsns.add(new Label("add")); 58 break; 59 case "-":vmInsns.add(new Label("sub")); 60 break; 61 case "*":vmInsns.add(new Label("mul")); 62 break; 63 case "/":vmInsns.add(new Label("div")); 64 break; 65 default: vmInsns.add(new Label("push " + s)); 66 } 67 } 68 vmInsns.add( 69 new Label("wrt"), 70 new Label("halt") 71 ); 72 73 }); 74 75 // 実行結果 76 Label result = new Label(); 77 executeButton.addClickListener(e -> { 78 result.setText(Integer.valueOf(out(data2)).toString()); 79 }); 80 81 add( 82 new HorizontalLayout(infixExpr, translateButton, generateButton, executeButton), 83 new H2("後置記法"), 84 postfixOut, 85 new H2("スタックマシン命令列"), 86 vmInsns, 87 new H2("実行結果"), 88 result 89 ); 90 } 91 92 public static int out(String[] data) { 93 //スタック 94 Stack<Integer> stack = new Stack<Integer>(); 95 96 Cal cal = new Cal(); 97 98 for(int i=0; i<data.length; i++) { 99 if(data[i].equals("+")) { 100 stack.add(cal.add(stack.pop(), stack.pop())); 101 continue; 102 } else if(data[i].equals("-")) { 103 stack.add(cal.sub(stack.pop(), stack.pop())); 104 continue; 105 } else if(data[i].equals("*")) { 106 stack.add(cal.mul(stack.pop(), stack.pop())); 107 continue; 108 } else if(data[i].equals("/")) { 109 stack.add(cal.div(stack.pop(), stack.pop())); 110 continue; 111 } else { 112 stack.push(Integer.parseInt(data[i])); 113 } 114 } 115 return stack.pop(); 116 } 117} 118 119
問題点①(解決済み??)
後置記法を出力部分のtranslateButton.addClickListener(e -> { }の中身の変数str,Node,str2,data2等で、『ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalである必要があります』というエラーが出ます。どのように変更すれば良いか教えてください。
問題点②
問題点①を踏まえて、変数の定義を全てラムダ式の中にしました。すると今度はstr2,data2,postfixOutのみが『シンボルを見つけられません』というエラーになります。
ラムダ式によりそのように表示されたということであれば、無名クラスの書き方に変えてみては如何でしょうか。
先回りになりますが、
「内部クラスからアクセス可能なローカル変数が final でなければならない理由」
https://happynow.hateblo.jp/entry/20120512/1336826316
という記事や記事内リンクをご理解頂けると良いかと思います。